From f40df753f2f5bde4b551ef8a54a5d3a761b0e8e6 Mon Sep 17 00:00:00 2001 From: JoeBakalor Date: Thu, 15 Jul 2021 16:07:37 -0500 Subject: [PATCH 1/6] clean up --- .vscode/settings.json | 49 +- libs/.DS_Store | Bin 14340 -> 14340 bytes libs/accelerometer/pxt.json | 6 +- libs/accelerometer_custom/accelhw.cpp | 42 +- libs/base/README.md | 5 + libs/base/_locales/base-jsdoc-strings.json | 266 --- libs/base/_locales/base-strings.json | 82 - libs/base/advmath.cpp | 26 + libs/base/buffer.cpp | 422 ++++ libs/base/buffer.ts | 453 ++++ libs/base/configkeys.h | 478 ++++ libs/base/console.ts | 138 ++ libs/base/control.cpp | 103 + libs/base/control.ts | 185 ++ libs/base/controlgc.cpp | 50 + libs/base/controlmessage.ts | 41 + libs/base/core.cpp | 2029 +++++++++++++++++ libs/base/docs/blocks/pause-until.md | 53 + libs/base/docs/device/error-codes.md | 53 + libs/base/docs/reference/console.md | 13 + libs/base/docs/reference/console/log-value.md | 38 + libs/base/docs/reference/console/log.md | 33 + libs/base/docs/reference/control.md | 25 + libs/base/docs/reference/control/assert.md | 33 + .../reference/control/device-dal-version.md | 25 + .../reference/control/device-serial-number.md | 25 + libs/base/docs/reference/control/millis.md | 25 + libs/base/docs/reference/control/on-event.md | 93 + libs/base/docs/reference/control/panic.md | 37 + .../docs/reference/control/raise-event.md | 61 + libs/base/docs/reference/control/reset.md | 20 + .../reference/control/run-in-background.md | 3 + .../docs/reference/control/run-in-parallel.md | 75 + .../docs/reference/control/wait-for-event.md | 63 + .../docs/reference/control/wait-micros.md | 26 + libs/base/docs/reference/input.md | 53 + libs/base/docs/reference/loops/forever.md | 33 + libs/base/docs/reference/loops/pause.md | 31 + .../docs/reference/text/convert-to-text.md | 34 + libs/base/enums.d.ts | 0 libs/base/eventcontext.ts | 289 +++ libs/base/fixed.ts | 75 + libs/base/forever.ts | 18 + libs/base/gc.cpp | 907 ++++++++ libs/base/gcstats.ts | 40 + libs/base/interval.ts | 72 + libs/base/json.ts | 322 +++ libs/base/loops.cpp | 27 + libs/base/math.ts | 83 + libs/base/ns.ts | 7 + libs/base/pause.ts | 19 + libs/base/perfcounters.ts | 13 + libs/base/poll.ts | 78 + libs/base/pxt.cpp | 518 +++++ libs/base/pxt.json | 13 +- libs/base/pxtbase.h | 1220 ++++++++++ libs/base/scheduling.ts | 56 + libs/base/shims.d.ts | 10 +- libs/base/sim/cfg.ts | 20 + libs/base/sim/control.ts | 220 ++ libs/base/sim/controlmessage.ts | 68 + libs/base/sim/core.ts | 14 + libs/base/sim/loops.ts | 4 + libs/base/sim/tsconfig.json | 15 + libs/base/templates.ts | 5 + libs/base/test.ts | 14 + libs/base/trig.cpp | 37 + libs/base/utfdecoder.ts | 83 + .../_locales/buttons-jsdoc-strings.json | 12 - libs/buttons/_locales/buttons-strings.json | 17 - libs/buttons/enums.d.ts | 19 - libs/buttons/pxt.json | 20 - libs/buttons/shims.d.ts | 69 - libs/core---nrf52/dal.d.ts | 258 +-- libs/core---nrf52/led.cpp | 8 +- libs/core---nrf52/led.h | 28 +- libs/core---nrf52/pxt.json | 2 - .../core---nrf52832-jsdoc-strings.json | 70 - .../_locales/core---nrf52832-strings.json | 51 - libs/core---nrf52832/dal.d.ts | 1128 --------- libs/core---nrf52832/enums.d.ts | 33 - libs/core---nrf52832/i2c.cpp | 1 - libs/core---nrf52832/i2c.ts | 1 - libs/core---nrf52832/platform.cpp | 64 - libs/core---nrf52832/platform.h | 119 - libs/core---nrf52832/pxt.json | 10 - libs/core---nrf52832/shims.d.ts | 318 --- libs/core/dal.d.ts | 339 ++- .../_locales/keyboard-jsdoc-strings.json | 8 - libs/keyboard/_locales/keyboard-strings.json | 55 - libs/keyboard/enums.d.ts | 107 - libs/keyboard/pxt.json | 3 - libs/keyboard/shims.d.ts | 17 - libs/lightsensor/pxt.json | 4 +- libs/servo/targetoverrides.ts | 6 - libs/switch/pxt.json | 6 +- libs/teknikio-bluebird/pxt.json | 1 - libs/touch/_locales/touch-jsdoc-strings.json | 8 - libs/touch/_locales/touch-strings.json | 9 - libs/touch/pxt.json | 21 - libs/touch/shims.d.ts | 69 - package-lock.json | 383 ---- package.json | 6 +- pxtarget.json | 4 - sim/simulator.ts | 21 +- sim/tsconfig.json | 5 +- sim/visuals/neopixel.ts | 238 -- yarn.lock | 418 +--- 108 files changed, 9372 insertions(+), 4058 deletions(-) create mode 100644 libs/base/README.md delete mode 100755 libs/base/_locales/base-jsdoc-strings.json delete mode 100755 libs/base/_locales/base-strings.json create mode 100644 libs/base/advmath.cpp create mode 100644 libs/base/buffer.cpp create mode 100644 libs/base/buffer.ts create mode 100644 libs/base/configkeys.h create mode 100644 libs/base/console.ts create mode 100644 libs/base/control.cpp create mode 100644 libs/base/control.ts create mode 100644 libs/base/controlgc.cpp create mode 100644 libs/base/controlmessage.ts create mode 100644 libs/base/core.cpp create mode 100644 libs/base/docs/blocks/pause-until.md create mode 100644 libs/base/docs/device/error-codes.md create mode 100644 libs/base/docs/reference/console.md create mode 100644 libs/base/docs/reference/console/log-value.md create mode 100644 libs/base/docs/reference/console/log.md create mode 100644 libs/base/docs/reference/control.md create mode 100644 libs/base/docs/reference/control/assert.md create mode 100644 libs/base/docs/reference/control/device-dal-version.md create mode 100644 libs/base/docs/reference/control/device-serial-number.md create mode 100644 libs/base/docs/reference/control/millis.md create mode 100644 libs/base/docs/reference/control/on-event.md create mode 100644 libs/base/docs/reference/control/panic.md create mode 100644 libs/base/docs/reference/control/raise-event.md create mode 100644 libs/base/docs/reference/control/reset.md create mode 100644 libs/base/docs/reference/control/run-in-background.md create mode 100644 libs/base/docs/reference/control/run-in-parallel.md create mode 100644 libs/base/docs/reference/control/wait-for-event.md create mode 100644 libs/base/docs/reference/control/wait-micros.md create mode 100644 libs/base/docs/reference/input.md create mode 100644 libs/base/docs/reference/loops/forever.md create mode 100644 libs/base/docs/reference/loops/pause.md create mode 100644 libs/base/docs/reference/text/convert-to-text.md mode change 100755 => 100644 libs/base/enums.d.ts create mode 100644 libs/base/eventcontext.ts create mode 100644 libs/base/fixed.ts create mode 100644 libs/base/forever.ts create mode 100644 libs/base/gc.cpp create mode 100644 libs/base/gcstats.ts create mode 100644 libs/base/interval.ts create mode 100644 libs/base/json.ts create mode 100644 libs/base/loops.cpp create mode 100644 libs/base/math.ts create mode 100644 libs/base/ns.ts create mode 100644 libs/base/pause.ts create mode 100644 libs/base/perfcounters.ts create mode 100644 libs/base/poll.ts create mode 100644 libs/base/pxt.cpp mode change 100755 => 100644 libs/base/pxt.json create mode 100644 libs/base/pxtbase.h create mode 100644 libs/base/scheduling.ts mode change 100755 => 100644 libs/base/shims.d.ts create mode 100644 libs/base/sim/cfg.ts create mode 100644 libs/base/sim/control.ts create mode 100644 libs/base/sim/controlmessage.ts create mode 100644 libs/base/sim/core.ts create mode 100644 libs/base/sim/loops.ts create mode 100644 libs/base/sim/tsconfig.json create mode 100644 libs/base/templates.ts create mode 100644 libs/base/test.ts create mode 100644 libs/base/trig.cpp create mode 100644 libs/base/utfdecoder.ts delete mode 100755 libs/buttons/_locales/buttons-jsdoc-strings.json delete mode 100755 libs/buttons/_locales/buttons-strings.json delete mode 100755 libs/buttons/enums.d.ts delete mode 100755 libs/buttons/pxt.json delete mode 100755 libs/buttons/shims.d.ts delete mode 100755 libs/core---nrf52832/_locales/core---nrf52832-jsdoc-strings.json delete mode 100755 libs/core---nrf52832/_locales/core---nrf52832-strings.json delete mode 100755 libs/core---nrf52832/dal.d.ts delete mode 100755 libs/core---nrf52832/enums.d.ts delete mode 100755 libs/core---nrf52832/i2c.cpp delete mode 100755 libs/core---nrf52832/i2c.ts delete mode 100755 libs/core---nrf52832/platform.cpp delete mode 100755 libs/core---nrf52832/platform.h delete mode 100755 libs/core---nrf52832/pxt.json delete mode 100755 libs/core---nrf52832/shims.d.ts delete mode 100755 libs/keyboard/_locales/keyboard-jsdoc-strings.json delete mode 100755 libs/keyboard/_locales/keyboard-strings.json delete mode 100755 libs/keyboard/enums.d.ts delete mode 100755 libs/keyboard/pxt.json delete mode 100755 libs/keyboard/shims.d.ts delete mode 100755 libs/servo/targetoverrides.ts delete mode 100755 libs/touch/_locales/touch-jsdoc-strings.json delete mode 100755 libs/touch/_locales/touch-strings.json delete mode 100755 libs/touch/pxt.json delete mode 100755 libs/touch/shims.d.ts delete mode 100755 sim/visuals/neopixel.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 7919dec1..b6e4f025 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,5 +18,52 @@ "tslint.enable": true, "tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib", "typescript.tsdk": "./node_modules/typescript/lib", - "editor.tabSize": 4 + "editor.tabSize": 4, + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" + } } \ No newline at end of file diff --git a/libs/.DS_Store b/libs/.DS_Store index 56e06c84e1ff60c0c2df878e02884f8ac8d05213..2c8104f1cc34ce6266e33ad366c00fc091777aa2 100755 GIT binary patch delta 131 zcmZoEXepTBFWS$*z`)GFAi%&-!jQ^P%ute>@8UA?qVi+|6BbrRpd`!WYnrN@KzRmh zAl8_?K|g%sgHLRm**RD^7~?np(zIvZ%&51EapGj@%{&6ZT$4GaXE5q-=22MBytz_^ gjb(DLrsw8wLYeG9i7A`e4Zg8#-mQ9s2`KCg0N_3*I{*Lx delta 937 zcmZoEXepTBFS?k4fq|KUL4bjwf+3ZmC@0-8I5~gfMdir`CM?Q~KuH!LW@X4_$V66< zTL2UV0@16J^%SHxo^;}8blR*S8q8JC%22|P&rr&c%#h)klb@WFlb-}s2Q;3s6^LK_ z2LrHPB$W_bVTSVQ0OgTnbMswXpyqJoU;37Qz4wqKx{4I23Uvk?N(wSS9)nroFgag- z&c+8>EQ|@8c@)+&*RwMu0Uccec6=T~F`Cmq1Fh3Qaypu7RObtZ09B)@K=y+DNw^o_ zs&s&12DCOeALb7R4s6OGswQuc5Z%02nT4gE9~jK}3`M|*(*?skAUlo0l);F>g29-< z2+bG32w<3j42QGIpy6i_#sj(VV*Q7lCErv9pL$$jSFm_pNrsSDw2;&lNdlm`)` zj1H6cs{2lypt_k?z>c||gCQFjD3!oS&1Xmix-kVUD8zwjkpn3xFw~=ZUUVPO^B8K7 qeJgej9;rZeW~i1UM=PpARCVBp^%dU1IPs*readRegister(ACCELEROMETER_TYPE_LIS3DH, LIS3DH_WHOAMI, &data, 1); - if (result ==0) - return ACCELEROMETER_TYPE_LIS3DH; - result = i2c->readRegister(ACCELEROMETER_TYPE_LIS3DH_ALT, LIS3DH_WHOAMI, &data, 1); - if (result ==0) - return ACCELEROMETER_TYPE_LIS3DH_ALT; -#endif #if PXT_SUPPORT_MMA8453 result = i2c->readRegister(ACCELEROMETER_TYPE_MMA8453, MMA8653_WHOAMI/*MMA8453 is similar to MMA8653*/ , &data, 1); if (result ==0) return ACCELEROMETER_TYPE_MMA8453; #endif - -#if PXT_SUPPORT_FXOS8700 - result = i2c->readRegister(ACCELEROMETER_TYPE_FXOS8700, FXOS8700_WHO_AM_I, &data, 1); - if (result ==0) - return ACCELEROMETER_TYPE_FXOS8700; -#endif #if PXT_SUPPORT_MMA8653 result = i2c->readRegister(ACCELEROMETER_TYPE_MMA8653, MMA8653_WHOAMI, &data, 1); @@ -191,22 +162,11 @@ class WAccel { codal::Accelerometer* instantiateAccelerometer(int accType, codal::I2C* i2c) { switch (accType) { -#if PXT_SUPPORT_LIS3DH - case ACCELEROMETER_TYPE_LIS3DH: - case ACCELEROMETER_TYPE_LIS3DH_ALT: - return new LIS3DH(*i2c, *LOOKUP_PIN(ACCELEROMETER_INT), space, accType); -#endif + #if PXT_SUPPORT_MSA300 case ACCELEROMETER_TYPE_MSA300: return new MSA300(*i2c, *LOOKUP_PIN(ACCELEROMETER_INT), space); #endif -#if PXT_SUPPORT_FXOS8700 - case ACCELEROMETER_TYPE_FXOS8700: { - // TODO: singleton when exposing gyro - auto fox = new FXOS8700(*i2c, *LOOKUP_PIN(ACCELEROMETER_INT)); - return new FXOS8700Accelerometer(*fox, space); - } -#endif #if PXT_SUPPORT_MMA8653 case ACCELEROMETER_TYPE_MMA8653: return new MMA8653(*i2c, *LOOKUP_PIN(ACCELEROMETER_INT), space); diff --git a/libs/base/README.md b/libs/base/README.md new file mode 100644 index 00000000..d61a17da --- /dev/null +++ b/libs/base/README.md @@ -0,0 +1,5 @@ +# base + +The base library, shared by all C++ targets (not only Codal-based). + + diff --git a/libs/base/_locales/base-jsdoc-strings.json b/libs/base/_locales/base-jsdoc-strings.json deleted file mode 100755 index a81831ee..00000000 --- a/libs/base/_locales/base-jsdoc-strings.json +++ /dev/null @@ -1,266 +0,0 @@ -{ - "Array": "Add, remove, and replace items in lists.", - "Array._popStatement": "Remove the last element from an array and return it.", - "Array._removeAtStatement": "Remove the element at a certain index.", - "Array._shiftStatement": "Remove the first element from an array and return it. This method changes the length of the array.", - "Array._unshiftStatement": "Add one element to the beginning of an array and return the new length of the array.", - "Array.concat": "Concatenates the values with another array.", - "Array.concat|param|arr": "The other array that is being concatenated with", - "Array.every": "Tests whether all elements in the array pass the test implemented by the provided function.", - "Array.every|param|callbackfn": "A function that accepts up to two arguments. The every method calls the callbackfn function one time for each element in the array.", - "Array.fill": "Fills all the elements of an array from a start index to an end index with a static value. The end index is not included.", - "Array.filter": "Return the elements of an array that meet the condition specified in a callback function.", - "Array.filter|param|callbackfn": "A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.", - "Array.find": "Returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.", - "Array.forEach": "Call a defined callback function on each element of an array.", - "Array.forEach|param|callbackfn": "A function that accepts up to two arguments. The forEach method calls the callbackfn function one time for each element in the array.", - "Array.get": "Get the value at a particular index", - "Array.get|param|index": "the zero-based position in the list of the item, eg: 0", - "Array.indexOf": "Return the index of the first occurrence of a value in an array.", - "Array.indexOf|param|fromIndex": "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.", - "Array.indexOf|param|item": "The value to locate in the array.", - "Array.insertAt": "Insert the value at a particular index, increases length by 1", - "Array.insertAt|param|index": "the zero-based position in the list to insert the value, eg: 0", - "Array.isArray": "Check if a given object is an array.", - "Array.join": "joins all elements of an array into a string and returns this string.", - "Array.join|param|sep": "the string separator", - "Array.length": "Get or set the length of an array. This number is one more than the index of the last element the array.", - "Array.map": "Call a defined callback function on each element of an array, and return an array containing the results.", - "Array.map|param|callbackfn": "A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.", - "Array.pop": "Remove the last element from an array and return it.", - "Array.push": "Append a new element to an array.", - "Array.reduce": "Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.", - "Array.reduce|param|callbackfn": "A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.", - "Array.reduce|param|initialValue": "Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.", - "Array.removeAt": "Remove the element at a certain index.", - "Array.removeElement": "Remove the first occurence of an object. Returns true if removed.", - "Array.reverse": "Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.", - "Array.set": "Store a value at a particular index", - "Array.set|param|index": "the zero-based position in the list to store the value, eg: 0", - "Array.shift": "Remove the first element from an array and return it. This method changes the length of the array.", - "Array.slice": "Return a section of an array.", - "Array.slice|param|end": "The end of the specified portion of the array. eg: 0", - "Array.slice|param|start": "The beginning of the specified portion of the array. eg: 0", - "Array.some": "Tests whether at least one element in the array passes the test implemented by the provided function.", - "Array.some|param|callbackfn": "A function that accepts up to two arguments. The some method calls the callbackfn function one time for each element in the array.", - "Array.sort": "Sort the elements of an array in place and returns the array. The sort is not necessarily stable.", - "Array.splice": "Remove elements from an array.", - "Array.splice|param|deleteCount": "The number of elements to remove. eg: 0", - "Array.splice|param|start": "The zero-based location in the array from which to start removing elements. eg: 0", - "Array.unshift": "Add one element to the beginning of an array and return the new length of the array.", - "Array@type": "Add, remove, and replace items in lists.", - "Boolean.toString": "Returns a string representation of an object.", - "Buffer.concat": "Return concatenation of current buffer and the given buffer", - "Buffer.fill": "Fill (a fragment) of the buffer with given value.", - "Buffer.getNumber": "Read a number in specified format from the buffer.", - "Buffer.getUint8": "Reads an unsigned byte at a particular location", - "Buffer.indexOf": "Return position of other buffer in current buffer", - "Buffer.isReadOnly": "Returns false when the buffer can be written to.", - "Buffer.length": "Returns the length of a Buffer object.", - "Buffer.rotate": "Rotate buffer left in place.\n\n\n\nstart. eg: -1", - "Buffer.rotate|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus", - "Buffer.rotate|param|offset": "number of bytes to shift; use negative value to shift right", - "Buffer.rotate|param|start": "start offset in buffer. Default is 0.", - "Buffer.setNumber": "Write a number in specified format in the buffer.", - "Buffer.setUint8": "Writes an unsigned byte at a particular location", - "Buffer.shift": "Shift buffer left in place, with zero padding.\n\n\n\nstart. eg: -1", - "Buffer.shift|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus", - "Buffer.shift|param|offset": "number of bytes to shift; use negative value to shift right", - "Buffer.shift|param|start": "start offset in buffer. Default is 0.", - "Buffer.slice": "Return a copy of a fragment of a buffer.", - "Buffer.toHex": "Convert a buffer to its hexadecimal representation.", - "Buffer.toString": "Convert a buffer to string assuming UTF8 encoding", - "Buffer.write": "Write contents of `src` at `dstOffset` in current buffer.", - "Infinity": "Constant representing positive infinity.", - "JSON.parse": "Converts a JavaScript Object Notation (JSON) string into an object.", - "JSON.stringify": "Converts a JavaScript value to a JavaScript Object Notation (JSON) string.", - "JSON.stringify|param|indent": "Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.", - "JSON.stringify|param|replacer": "Not supported; use null.", - "JSON.stringify|param|value": "A JavaScript value, usually an object or array, to be converted.", - "Math": "More complex operations with numbers.", - "Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.", - "Math.abs|param|x": "A numeric expression for which the absolute value is needed.", - "Math.acos": "Returns the arccosine (in radians) of a number", - "Math.acos|param|x": "A number", - "Math.asin": "Returns the arcsine (in radians) of a number", - "Math.asin|param|x": "A number", - "Math.atan": "Returns the arctangent (in radians) of a number", - "Math.atan2": "Returns the arctangent of the quotient of its arguments.", - "Math.atan2|param|x": "A number", - "Math.atan2|param|y": "A number", - "Math.atan|param|x": "A number", - "Math.ceil": "Returns the smallest number greater than or equal to its numeric argument.", - "Math.ceil|param|x": "A numeric expression.", - "Math.constrain": "Constrains a number to be within a range", - "Math.cos": "Returns the cosine of a number.", - "Math.cos|param|x": "An angle in radians", - "Math.exp": "Returns returns ``e^x``.", - "Math.exp|param|x": "A number", - "Math.floor": "Returns the greatest number less than or equal to its numeric argument.", - "Math.floor|param|x": "A numeric expression.", - "Math.icos": "Returns the cosine of an input angle. This is an 8-bit approximation.", - "Math.icos|param|theta": "input angle from 0-255", - "Math.idiv": "Returns the value of integer signed 32 bit division of two numbers.", - "Math.idiv|param|x": "The first number", - "Math.idiv|param|y": "The second number", - "Math.imul": "Returns the value of integer signed 32 bit multiplication of two numbers.", - "Math.imul|param|x": "The first number", - "Math.imul|param|y": "The second number", - "Math.isin": "Returns the sine of an input angle. This is an 8-bit approximation.", - "Math.isin|param|theta": "input angle from 0-255", - "Math.log": "Returns the natural logarithm (base e) of a number.", - "Math.log|param|x": "A number", - "Math.map": "Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc.", - "Math.map|param|fromHigh": "the upper bound of the value's current range, eg: 1023", - "Math.map|param|fromLow": "the lower bound of the value's current range", - "Math.map|param|toHigh": "the upper bound of the value's target range, eg: 4", - "Math.map|param|toLow": "the lower bound of the value's target range", - "Math.map|param|value": "value to map in ranges", - "Math.max": "Returns the larger of two supplied numeric expressions.", - "Math.min": "Returns the smaller of two supplied numeric expressions.", - "Math.pow": "Returns the value of a base expression taken to a specified power.", - "Math.pow|param|x": "The base value of the expression.", - "Math.pow|param|y": "The exponent value of the expression.", - "Math.random": "Returns a pseudorandom number between 0 and 1.", - "Math.randomRange": "Returns a pseudorandom number between min and max included.\nIf both numbers are integral, the result is integral.", - "Math.randomRange|param|max": "the upper inclusive bound, eg: 10", - "Math.randomRange|param|min": "the lower inclusive bound, eg: 0", - "Math.round": "Returns a supplied numeric expression rounded to the nearest number.", - "Math.roundWithPrecision": "Rounds ``x`` to a number with the given number of ``digits``", - "Math.roundWithPrecision|param|digits": "the number of resulting digits", - "Math.roundWithPrecision|param|x": "the number to round", - "Math.round|param|x": "The value to be rounded to the nearest number.", - "Math.sign": "Returns the sign of the x, indicating whether x is positive, negative or zero.", - "Math.sign|param|x": "The numeric expression to test", - "Math.sin": "Returns the sine of a number.", - "Math.sin|param|x": "An angle in radians", - "Math.sqrt": "Returns the square root of a number.", - "Math.sqrt|param|x": "A numeric expression.", - "Math.tan": "Returns the tangent of a number.", - "Math.tan|param|x": "An angle in radians", - "Math.trunc": "Returns the number with the decimal part truncated.", - "Math.trunc|param|x": "A numeric expression.", - "NaN": "Constant representing Not-A-Number.", - "Number.isNaN": "Check if a given value is of type Number and it is a NaN.", - "Number.toString": "Returns a string representation of a number.", - "Object.keys": "Return the field names in an object.", - "String": "Combine, split, and search text strings.", - "String.charAt": "Return the character at the specified index.", - "String.charAt|param|index": "The zero-based index of the desired character.", - "String.charCodeAt": "Return the Unicode value of the character at the specified location.", - "String.charCodeAt|param|index": "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.", - "String.compare": "See how the order of characters in two strings is different (in ASCII encoding).", - "String.compare|param|that": "String to compare to target string", - "String.concat": "Returns a string that contains the concatenation of two or more strings.", - "String.concat|param|other": "The string to append to the end of the string.", - "String.fromCharCode": "Make a string from the given ASCII character code.", - "String.includes": "Determines whether a string contains the characters of a specified string.", - "String.includes|param|searchValue": "the text to find", - "String.includes|param|start": "optional start index for the search", - "String.indexOf": "Returns the position of the first occurrence of a specified value in a string.", - "String.indexOf|param|searchValue": "the text to find", - "String.indexOf|param|start": "optional start index for the search", - "String.isEmpty": "Returns a value indicating if the string is empty", - "String.length": "Returns the length of a String object.", - "String.replace": "Return the current string with the first occurence of toReplace\nreplaced with the replacer\n\n\nor a function that accepts the substring and returns the replacement string.", - "String.replaceAll": "Return the current string with each occurence of toReplace\nreplaced with the replacer\n\n\nor a function that accepts the substring and returns the replacement string.", - "String.replaceAll|param|replacer": "either the string that replaces toReplace in the current string,", - "String.replaceAll|param|toReplace": "the substring to replace in the current string", - "String.replace|param|replacer": "either the string that replaces toReplace in the current string,", - "String.replace|param|toReplace": "the substring to replace in the current string", - "String.slice": "Return a substring of the current string.", - "String.slice|param|end": "one-past-last character index", - "String.slice|param|start": "first character index; can be negative from counting from the end, eg:0", - "String.split": "Splits the string according to the separators", - "String.split|param|separator": "@param limit", - "String.substr": "Return a substring of the current string.", - "String.substr|param|length": "number of characters to extract", - "String.substr|param|start": "first character index; can be negative from counting from the end, eg:0", - "String.toLowerCase": "Converts the string to lower case characters.", - "String.trim": "Return a substring of the current string with whitespace removed from both ends", - "String@type": "Combine, split, and search text strings.", - "StringMap": "A dictionary from string key to string values", - "clearImmediate": "Cancels the immediate actions.", - "clearInterval": "Cancels repeated action which was set up using setInterval().", - "clearTimeout": "Clears the delay set by setTimeout().", - "console": "Reading and writing data to the console output.", - "console.addListener": "Adds a listener for the log messages", - "console.inspect": "Convert any object or value to a string representation", - "console.inspect|param|maxElements": "[optional] max number values in an object to include in output", - "console.inspect|param|obj": "value to be converted to a string", - "console.log": "Write a line of text to the console output.", - "console.logValue": "Write a name:value pair as a line of text to the console output.", - "console.logValue|param|name": "name of the value stream, eg: \"x\"", - "console.logValue|param|value": "to write", - "console.log|param|value": "to send", - "console.minPriority": "Minimum priority to send messages to listeners", - "console.removeListener": "Removes a listener", - "control": "Program controls and events.", - "control.AnimationQueue.cancel": "Cancels the current running animation and clears the queue", - "control.AnimationQueue.runUntilDone": "Runs 'render' in a loop until it returns false or the 'stop' function is called", - "control.assert": "Display an error code and stop the program when the assertion is `false`.", - "control.benchmark": "Runs the function and returns run time in microseconds.", - "control.createBuffer": "Create a new zero-initialized buffer.", - "control.createBufferFromUTF8": "Create a new buffer with UTF8-encoded string", - "control.createBufferFromUTF8|param|str": "the string to put in the buffer", - "control.createBuffer|param|size": "number of bytes in the buffer", - "control.deviceLongSerialNumber": "Derive a unique, consistent 64-bit serial number of this device from internal data.", - "control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.", - "control.dmesgPerfCounters": "Dump values of profiling performance counters.", - "control.dmesgValue": "Dump internal information about a value.", - "control.enablePerfCounter": "Enable profiling for current function.", - "control.eventContext": "Gets the current event context if any", - "control.gc": "Force GC and dump basic information about heap.", - "control.gcStats": "Get various statistics about the garbage collector (GC)", - "control.heapDump": "Force GC and halt waiting for debugger to do a full heap dump.", - "control.heapSnapshot": "Record a heap snapshot to debug memory leaks.", - "control.internalOnEvent": "Used internally", - "control.micros": "Gets current time in microseconds. Overflows every ~18 minutes.", - "control.millis": "Gets the number of milliseconds elapsed since power on.", - "control.onEvent": "Run code when a registered event happens.", - "control.onEvent|param|value": "the event value to match", - "control.onIdle": "Registers a function to run when the device is idling", - "control.panic": "Display an error code and stop the program.", - "control.panic|param|code": "an error number to display. eg: 5", - "control.popEventContext": "Pops the current event context and restore handlers if any previous context", - "control.profilingEnabled": "Return true if profiling is enabled in the current build.", - "control.pushEventContext": "Pushes a new event context and clears all handlers", - "control.ramSize": "Returns estimated size of memory in bytes.", - "control.reset": "Reset the device.", - "control.runInBackground": "Deprecated, use ``control.runInParallel`` instead.", - "control.runInParallel": "Run other code in the parallel.", - "control.setDebugFlags": "Set flags used when connecting an external debugger.", - "control.waitForEvent": "Blocks the calling thread until the specified event is raised.", - "control.waitMicros": "Block the current fiber for the given microseconds", - "control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4", - "convertToText": "Convert any value to text", - "convertToText|param|value": "value to be converted to text", - "forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.", - "hex": "Tagged hex literal converter", - "loops.forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.", - "loops.pause": "Pause for the specified time in milliseconds", - "loops.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000", - "msgpack.packNumberArray": "Pack a number array into a buffer.", - "msgpack.packNumberArray|param|nums": "the numbers to be packed", - "msgpack.unpackNumberArray": "Unpacks a buffer into a number array.", - "parseFloat": "Convert a string to a number.", - "parseInt": "Convert a string to an integer.\n\n\nIf this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.\nAll other strings are considered decimal.", - "parseInt|param|radix": "optional A value between 2 and 36 that specifies the base of the number in text.", - "parseInt|param|text": "A string to convert into an integral number. eg: \"123\"", - "pause": "Pause for the specified time in milliseconds", - "pauseUntil": "Busy wait for a condition to be true", - "pauseUntil|param|condition": "condition to test for", - "pauseUntil|param|timeOut": "if positive, maximum duration to wait for in milliseconds", - "pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000", - "pins.createBufferFromArray": "Create a new buffer initalized to bytes from given array.", - "pins.createBufferFromArray|param|bytes": "data to initalize with", - "pins.sizeOf": "Get the size in bytes of specified number format.", - "randint": "Returns a pseudorandom number between min and max included.\nIf both numbers are integral, the result is integral.", - "randint|param|max": "the upper inclusive bound, eg: 10", - "randint|param|min": "the lower inclusive bound, eg: 0", - "setImmediate": "Calls a function as soon as possible.", - "setInterval": "Calls a function with a fixed time delay between each call to that function.", - "setInterval|param|func": "@param delay ", - "setTimeout": "Calls a function after specified delay.", - "setTimeout|param|func": "@param delay " -} \ No newline at end of file diff --git a/libs/base/_locales/base-strings.json b/libs/base/_locales/base-strings.json deleted file mode 100755 index 2d7ca3e5..00000000 --- a/libs/base/_locales/base-strings.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "Array._popStatement|block": "remove last value from %list", - "Array._removeAtStatement|block": "%list| remove value at %index", - "Array._shiftStatement|block": "remove first value from %list", - "Array._unshiftStatement|block": "%list| insert %value| at beginning", - "Array.indexOf|block": "%list| find index of %value", - "Array.insertAt|block": "%list| insert at %index| value %value", - "Array.length|block": "length of %VALUE", - "Array.pop|block": "get and remove last value from %list", - "Array.push|block": "%list| add value %value| to end", - "Array.removeAt|block": "%list| get and remove value at %index", - "Array.reverse|block": "reverse %list", - "Array.shift|block": "get and remove first value from %list", - "Array.unshift|block": "%list| insert %value| at beginning", - "Array|block": "Array", - "JSON|block": "JSON", - "Math.constrain|block": "constrain %value|between %low|and %high", - "Math.map|block": "map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh", - "Math.randomRange|block": "pick random %min|to %limit", - "Math|block": "Math", - "Number|block": "Number", - "Object|block": "Object", - "String.charAt|block": "char from %this=text|at %pos", - "String.compare|block": "compare %this=text| to %that", - "String.fromCharCode|block": "text from char code %code", - "String.includes|block": "%this=text|includes %searchValue", - "String.indexOf|block": "%this=text|find index of %searchValue", - "String.isEmpty|block": "%this=text| is empty", - "String.length|block": "length of %VALUE", - "String.split|block": "split %this=text|at %separator", - "String.substr|block": "substring of %this=text|from %start|of length %length", - "String|block": "String", - "console.logValue|block": "console|log value %name|= %value", - "console.log|block": "console log $value", - "console|block": "console", - "control.assert|block": "assert %cond|with value %code", - "control.deviceLongSerialNumber|block": "device long serial number", - "control.deviceSerialNumber|block": "device serial number", - "control.millis|block": "millis (ms)", - "control.onEvent|block": "on event|from %src|with value %value", - "control.panic|block": "panic %code", - "control.reset|block": "reset", - "control.runInBackground|block": "run in background", - "control.runInParallel|block": "run in parallel", - "control.waitForEvent|block": "wait for event|from %src|with value %value", - "control.waitMicros|block": "wait (µs)%micros", - "control|block": "control", - "convertToText|block": "convert $value=math_number to text", - "forever|block": "forever", - "loops.forever|block": "forever", - "loops.pause|block": "pause %pause=timePicker|ms", - "loops|block": "loops", - "msgpack|block": "msgpack", - "parseFloat|block": "parse to number %text", - "parseInt|block": "parse to integer %text", - "pause|block": "pause %pause=timePicker|ms", - "pins|block": "pins", - "randint|block": "pick random %min|to %limit", - "{id:category}Array": "Array", - "{id:category}Arrays": "Arrays", - "{id:category}Basic": "Basic", - "{id:category}Boolean": "Boolean", - "{id:category}Buffer": "Buffer", - "{id:category}Console": "Console", - "{id:category}Control": "Control", - "{id:category}Fx": "Fx", - "{id:category}Fx8": "Fx8", - "{id:category}Helpers": "Helpers", - "{id:category}JSON": "JSON", - "{id:category}Loops": "Loops", - "{id:category}Math": "Math", - "{id:category}Msgpack": "Msgpack", - "{id:category}Number": "Number", - "{id:category}Object": "Object", - "{id:category}Pins": "Pins", - "{id:category}String": "String", - "{id:category}Text": "Text", - "{id:category}UTF8Decoder": "UTF8Decoder", - "{id:group}Modify": "Modify", - "{id:group}Operations": "Operations", - "{id:group}Read": "Read" -} \ No newline at end of file diff --git a/libs/base/advmath.cpp b/libs/base/advmath.cpp new file mode 100644 index 00000000..df2828b6 --- /dev/null +++ b/libs/base/advmath.cpp @@ -0,0 +1,26 @@ +#include "pxtbase.h" + +using namespace std; + +#define SINGLE(op) return fromDouble(::op(toDouble(x))); + +namespace Math_ { + +//% +TNumber log2(TNumber x){SINGLE(log2)} +//% +TNumber exp(TNumber x){SINGLE(exp)} +//% +TNumber tanh(TNumber x){SINGLE(tanh)} +//% +TNumber sinh(TNumber x){SINGLE(sinh)} +//% +TNumber cosh(TNumber x){SINGLE(cosh)} +//% +TNumber atanh(TNumber x){SINGLE(atanh)} +//% +TNumber asinh(TNumber x){SINGLE(asinh)} +//% +TNumber acosh(TNumber x){SINGLE(acosh)} + +} \ No newline at end of file diff --git a/libs/base/buffer.cpp b/libs/base/buffer.cpp new file mode 100644 index 00000000..cd8823ef --- /dev/null +++ b/libs/base/buffer.cpp @@ -0,0 +1,422 @@ +#include "pxtbase.h" +#include + +using namespace std; + +//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte +namespace BufferMethods { +//% +uint8_t *getBytes(Buffer buf) { + return buf->data; +} + +//% +int getByte(Buffer buf, int off) { + if (buf && 0 <= off && off < buf->length) + return buf->data[off]; + return 0; +} + +//% +void setByte(Buffer buf, int off, int v) { + if (buf && 0 <= off && off < buf->length) + buf->data[off] = v; +} + +/** +* Reads an unsigned byte at a particular location +*/ +//% +int getUint8(Buffer buf, int off) { + return getByte(buf, off); +} + +/** + * Returns false when the buffer can be written to. + */ +//% +bool isReadOnly(Buffer buf) { + return buf->isReadOnly(); +} + +/** +* Writes an unsigned byte at a particular location +*/ +//% +void setUint8(Buffer buf, int off, int v) { + setByte(buf, off, v); +} + +int writeBuffer(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1) { + if (length < 0) + length = src->length; + + if (srcOffset < 0 || dstOffset < 0 || dstOffset > buf->length) + return -1; + + length = min(src->length - srcOffset, buf->length - dstOffset); + + if (length < 0) + return -1; + + if (buf == src) { + memmove(buf->data + dstOffset, src->data + srcOffset, length); + } else { + memcpy(buf->data + dstOffset, src->data + srcOffset, length); + } + + return 0; +} + +/** + * Write a number in specified format in the buffer. + */ +//% +void setNumber(Buffer buf, NumberFormat format, int offset, TNumber value) { + if (offset < 0) + return; + setNumberCore(buf->data + offset, buf->length - offset, format, value); +} + +/** + * Read a number in specified format from the buffer. + */ +//% +TNumber getNumber(Buffer buf, NumberFormat format, int offset) { + if (offset < 0) + return fromInt(0); + return getNumberCore(buf->data + offset, buf->length - offset, format); +} + +/** Returns the length of a Buffer object. */ +//% property +int length(Buffer s) { + return s->length; +} + +/** + * Fill (a fragment) of the buffer with given value. + */ +//% +void fill(Buffer buf, int value, int offset = 0, int length = -1) { + if (offset < 0 || offset > buf->length) + return; // DEVICE_INVALID_PARAMETER; + if (length < 0) + length = buf->length; + length = min(length, buf->length - offset); + memset(buf->data + offset, value, length); +} + +/** + * Return a copy of a fragment of a buffer. + */ +//% +Buffer slice(Buffer buf, int offset = 0, int length = -1) { + offset = min((int)buf->length, offset); + if (length < 0) + length = buf->length; + length = min(length, buf->length - offset); + return mkBuffer(buf->data + offset, length); +} + +/** + * Shift buffer left in place, with zero padding. + * @param offset number of bytes to shift; use negative value to shift right + * @param start start offset in buffer. Default is 0. + * @param length number of elements in buffer. If negative, length is set as the buffer length minus + * start. eg: -1 + */ +//% +void shift(Buffer buf, int offset, int start = 0, int length = -1) { + if (length < 0) + length = buf->length - start; + if (start < 0 || start + length > buf->length || start + length < start || length == 0 || + offset == 0 || offset == INT_MIN) + return; + if (offset <= -length || offset >= length) { + fill(buf, 0); + return; + } + + uint8_t *data = buf->data + start; + if (offset < 0) { + offset = -offset; + memmove(data + offset, data, length - offset); + memset(data, 0, offset); + } else { + length = length - offset; + memmove(data, data + offset, length); + memset(data + length, 0, offset); + } +} + +/** + * Convert a buffer to string assuming UTF8 encoding + */ +//% +String toString(Buffer buf) { + return mkString((char *)buf->data, buf->length); +} + +/** + * Convert a buffer to its hexadecimal representation. + */ +//% +String toHex(Buffer buf) { + const char *hex = "0123456789abcdef"; + auto res = mkStringCore(NULL, buf->length * 2); + for (int i = 0; i < buf->length; ++i) { + res->ascii.data[i << 1] = hex[buf->data[i] >> 4]; + res->ascii.data[(i << 1) + 1] = hex[buf->data[i] & 0xf]; + } + return res; +} + +/** + * Rotate buffer left in place. + * @param offset number of bytes to shift; use negative value to shift right + * @param start start offset in buffer. Default is 0. + * @param length number of elements in buffer. If negative, length is set as the buffer length minus + * start. eg: -1 + */ +//% +void rotate(Buffer buf, int offset, int start = 0, int length = -1) { + if (length < 0) + length = buf->length - start; + if (start < 0 || start + length > buf->length || start + length < start || length == 0 || + offset == 0 || offset == INT_MIN) + return; + + if (offset < 0) + offset += length << 8; // try to make it positive + offset %= length; + if (offset < 0) + offset += length; + + uint8_t *data = buf->data + start; + + uint8_t *n_first = data + offset; + uint8_t *first = data; + uint8_t *next = n_first; + uint8_t *last = data + length; + + while (first != next) { + uint8_t tmp = *first; + *first++ = *next; + *next++ = tmp; + if (next == last) { + next = n_first; + } else if (first == n_first) { + n_first = next; + } + } +} + +/** + * Write contents of `src` at `dstOffset` in current buffer. + */ +//% +void write(Buffer buf, int dstOffset, Buffer src) { + // srcOff and length not supported, we only do up to 4 args :/ + writeBuffer(buf, dstOffset, src, 0, -1); +} + +/** + * Compute k-bit FNV-1 non-cryptographic hash of the buffer. + */ +//% +uint32_t hash(Buffer buf, int bits) { + if (bits < 1) + return 0; + uint32_t h = hash_fnv1(buf->data, buf->length); + if (bits >= 32) + return h; + else + return ((h ^ (h >> bits)) & ((1 << bits) - 1)); +} + +} // namespace BufferMethods + +// The functions below are deprecated in control namespace, but they are referenced +// in Buffer namespaces via explicit shim=... +namespace control { +/** + * Create a new zero-initialized buffer. + * @param size number of bytes in the buffer + */ +//% deprecated=1 +Buffer createBuffer(int size) { + return mkBuffer(NULL, size); +} + + +/** + * Create a new buffer with UTF8-encoded string + * @param str the string to put in the buffer + */ +//% deprecated=1 +Buffer createBufferFromUTF8(String str) { +#if PXT_UTF8 + auto sz = toRealUTF8(str, NULL); + auto r = mkBuffer(NULL, sz); + toRealUTF8(str, r->data); + return r; +#else + return mkBuffer((const uint8_t *)str->getUTF8Data(), str->getUTF8Size()); +#endif +} +} // namespace control + +namespace pxt { +static int writeBytes(uint8_t *dst, uint8_t *src, int length, bool swapBytes, int szLeft) { + if (szLeft < length) { + return -1; + } + + if (swapBytes) { + uint8_t *p = dst + length; + for (int i = 0; i < length; ++i) + *--p = src[i]; + } else { + if (length == 4 && ((uintptr_t)dst & 3) == 0) + *(uint32_t *)dst = *(uint32_t *)src; + else if (length == 2 && ((uintptr_t)dst & 1) == 0) + *(uint16_t *)dst = *(uint16_t *)src; + else + memcpy(dst, src, length); + } + + return 0; +} + +static int readBytes(uint8_t *src, uint8_t *dst, int length, bool swapBytes, int szLeft) { + if (szLeft < length) { + memset(dst, 0, length); + return -1; + } + + if (swapBytes) { + uint8_t *p = src + length; + for (int i = 0; i < length; ++i) + dst[i] = *--p; + } else { + if (length == 4 && ((uintptr_t)src & 3) == 0) + *(uint32_t *)dst = *(uint32_t *)src; + else if (length == 2 && ((uintptr_t)src & 1) == 0) + *(uint16_t *)dst = *(uint16_t *)src; + else + memcpy(dst, src, length); + } + + return 0; +} + +void setNumberCore(uint8_t *buf, int szLeft, NumberFormat format, TNumber value) { + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + float f32; + double f64; + +// Assume little endian +#define WRITEBYTES(isz, swap, toInt) \ + isz = toInt(value); \ + writeBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ + break + + switch (format) { + case NumberFormat::Int8LE: + WRITEBYTES(i8, false, toInt); + case NumberFormat::UInt8LE: + WRITEBYTES(u8, false, toInt); + case NumberFormat::Int16LE: + WRITEBYTES(i16, false, toInt); + case NumberFormat::UInt16LE: + WRITEBYTES(u16, false, toInt); + case NumberFormat::Int32LE: + WRITEBYTES(i32, false, toInt); + case NumberFormat::UInt32LE: + WRITEBYTES(u32, false, toUInt); + + case NumberFormat::Int8BE: + WRITEBYTES(i8, true, toInt); + case NumberFormat::UInt8BE: + WRITEBYTES(u8, true, toInt); + case NumberFormat::Int16BE: + WRITEBYTES(i16, true, toInt); + case NumberFormat::UInt16BE: + WRITEBYTES(u16, true, toInt); + case NumberFormat::Int32BE: + WRITEBYTES(i32, true, toInt); + case NumberFormat::UInt32BE: + WRITEBYTES(u32, true, toUInt); + + case NumberFormat::Float32LE: + WRITEBYTES(f32, false, toFloat); + case NumberFormat::Float32BE: + WRITEBYTES(f32, true, toFloat); + case NumberFormat::Float64LE: + WRITEBYTES(f64, false, toDouble); + case NumberFormat::Float64BE: + WRITEBYTES(f64, true, toDouble); + } +} + +TNumber getNumberCore(uint8_t *buf, int szLeft, NumberFormat format) { + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + int32_t i32; + uint32_t u32; + float f32; + double f64; + +// Assume little endian +#define READBYTES(isz, swap, conv) \ + readBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ + return conv(isz) + + switch (format) { + case NumberFormat::Int8LE: + READBYTES(i8, false, fromInt); + case NumberFormat::UInt8LE: + READBYTES(u8, false, fromInt); + case NumberFormat::Int16LE: + READBYTES(i16, false, fromInt); + case NumberFormat::UInt16LE: + READBYTES(u16, false, fromInt); + case NumberFormat::Int32LE: + READBYTES(i32, false, fromInt); + case NumberFormat::UInt32LE: + READBYTES(u32, false, fromUInt); + + case NumberFormat::Int8BE: + READBYTES(i8, true, fromInt); + case NumberFormat::UInt8BE: + READBYTES(u8, true, fromInt); + case NumberFormat::Int16BE: + READBYTES(i16, true, fromInt); + case NumberFormat::UInt16BE: + READBYTES(u16, true, fromInt); + case NumberFormat::Int32BE: + READBYTES(i32, true, fromInt); + case NumberFormat::UInt32BE: + READBYTES(u32, true, fromUInt); + + case NumberFormat::Float32LE: + READBYTES(f32, false, fromFloat); + case NumberFormat::Float32BE: + READBYTES(f32, true, fromFloat); + case NumberFormat::Float64LE: + READBYTES(f64, false, fromDouble); + case NumberFormat::Float64BE: + READBYTES(f64, true, fromDouble); + } + + return 0; +} +} // namespace pxt diff --git a/libs/base/buffer.ts b/libs/base/buffer.ts new file mode 100644 index 00000000..60649a11 --- /dev/null +++ b/libs/base/buffer.ts @@ -0,0 +1,453 @@ +namespace pins { + //% deprecated=1 + export function sizeOf(format: NumberFormat) { + return Buffer.sizeOfNumberFormat(format) + } + + //% deprecated=1 + export function createBufferFromArray(bytes: number[]) { + return Buffer.fromArray(bytes) + } + + //% deprecated=1 + export function packedSize(format: string) { + return Buffer.packedSize(format) + } + + //% deprecated=1 + export function packBuffer(format: string, nums: number[]) { + return Buffer.pack(format, nums) + } + + //% deprecated=1 + export function packIntoBuffer(format: string, buf: Buffer, offset: number, nums: number[]) { + buf.packAt(offset, format, nums) + } + + //% deprecated=1 + export function unpackBuffer(format: string, buf: Buffer, offset = 0) { + return buf.unpack(format, offset) + } + + //% deprecated=1 + export function concatBuffers(bufs: Buffer[]) { + return Buffer.concat(bufs) + } +} + +// see http://msgpack.org/ for the spec +// it currently only implements numbers and their sequances +// once we handle any type and typeof expressions we can do more + +namespace msgpack { + function tagFormat(tag: number) { + switch (tag) { + case 0xCB: return NumberFormat.Float64BE + case 0xCC: return NumberFormat.UInt8BE + case 0xCD: return NumberFormat.UInt16BE + case 0xCE: return NumberFormat.UInt32BE + case 0xD0: return NumberFormat.Int8BE + case 0xD1: return NumberFormat.Int16BE + case 0xD2: return NumberFormat.Int32BE + default: + return null + } + } + + function packNumberCore(buf: Buffer, offset: number, num: number) { + let tag = 0xCB + if (num == (num << 0) || num == (num >>> 0)) { + if (-31 <= num && num <= 127) { + if (buf) buf[offset] = num + return 1 + } else if (0 <= num) { + if (num <= 0xff) { + tag = 0xCC + } else if (num <= 0xffff) { + tag = 0xCD + } else { + tag = 0xCE + } + } else { + if (-0x7f <= num) { + tag = 0xD0 + } else if (-0x7fff <= num) { + tag = 0xD1 + } else { + tag = 0xD2 + } + } + } + let fmt = tagFormat(tag) + if (buf) { + buf[offset] = tag + buf.setNumber(fmt, offset + 1, num) + } + return pins.sizeOf(fmt) + 1 + } + + /** + * Unpacks a buffer into a number array. + */ + export function unpackNumberArray(buf: Buffer, offset = 0): number[] { + let res: number[] = [] + + while (offset < buf.length) { + let fmt = tagFormat(buf[offset++]) + if (fmt === null) { + let v = buf.getNumber(NumberFormat.Int8BE, offset - 1) + if (-31 <= v && v <= 127) + res.push(v) + else + return null + } else { + res.push(buf.getNumber(fmt, offset)) + offset += pins.sizeOf(fmt) + } + // padding at the end + while (buf[offset] === 0xc1) offset++; + } + + return res + } + + /** + * Pack a number array into a buffer. + * @param nums the numbers to be packed + */ + export function packNumberArray(nums: number[]): Buffer { + let off = 0 + for (let n of nums) { + off += packNumberCore(null, off, n) + } + let buf = Buffer.create(off) + off = 0 + for (let n of nums) { + off += packNumberCore(buf, off, n) + } + return buf + } +} + +namespace helpers { + export function bufferConcat(a: Buffer, b: Buffer) { + const r = Buffer.create(a.length + b.length) + r.write(0, a) + r.write(a.length, b) + return r + } + + export function bufferEquals(l: Buffer, r: Buffer) { + if (!l || !r) return !!l == !!r; + if (l.length != r.length) return false; + for (let i = 0; i < l.length; ++i) { + if (l[i] != r[i]) + return false; + } + return true; + } + + export function bufferIndexOf(a: Buffer, b: Buffer) { + for (let i = 0; i <= a.length - b.length; ++i) { + if (a[i] == b[0]) { + let j = 0 + while (j < b.length) { + if (a[i + j] != b[j]) + break + j++ + } + if (j >= b.length) + return i + } + } + return -1 + } + + export function bufferUnpack(buf: Buffer, format: string, offset?: number) { + if (!offset) offset = 0 + let res: number[] = [] + Buffer.__packUnpackCore(format, res, buf, false, offset) + return res + } + + export function bufferPackAt(buf: Buffer, offset: number, format: string, nums: number[]) { + Buffer.__packUnpackCore(format, nums, buf, true, offset) + } + + export function bufferChunked(buf: Buffer, maxBytes: number) { + if (buf.length <= maxBytes) return [buf] + else { + const r: Buffer[] = [] + for (let i = 0; i < buf.length; i += maxBytes) + r.push(buf.slice(i, maxBytes)) + return r + } + } + + export function bufferToArray(buf: Buffer, format: NumberFormat) { + const sz = Buffer.sizeOfNumberFormat(format) + const len = buf.length - sz + const r: number[] = [] + for (let i = 0; i <= len; i += sz) + r.push(buf.getNumber(format, i)) + return r + } +} + +interface Buffer { + [index: number]: number; + + /** + * Return concatenation of current buffer and the given buffer + */ + //% helper=bufferConcat + concat(other: Buffer): Buffer; + + /** + * Return position of other buffer in current buffer + */ + //% helper=bufferIndexOf + indexOf(other: Buffer): number; + + /** + * Reads numbers from the buffer according to the format + */ + //% helper=bufferUnpack + unpack(format: string, offset?: number): number[]; + + /** + * Writes numbers to the buffer according to the format + */ + //% helper=bufferPackAt + packAt(offset: number, format: string, nums: number[]): void; + + /** + * Returns true if this and the other buffer hold the same data + */ + //% helper=bufferEquals + equals(other: Buffer): boolean; + + /** + * Splits buffer into parts no larger than specified + */ + //% helper=bufferChunked + chunked(maxSize: number): Buffer[]; + + + /** + * Read contents of buffer as an array in specified format + */ + //% helper=bufferToArray + toArray(format: NumberFormat): number[]; + + // rest defined in buffer.cpp +} + +namespace Buffer { + /** + * Allocate a new buffer. + * @param size number of bytes in the buffer + */ + //% shim=control::createBuffer + export declare function create(size: number): Buffer; + + /** + * Create a new buffer, decoding a hex string + */ + export function fromHex(hex: string) { + const hexStr = "0123456789abcdef" + const res = Buffer.create(hex.length >> 1) + hex = hex.toLowerCase() + for (let i = 0; i < hex.length; i += 2) { + const p0 = hexStr.indexOf(hex.charAt(i)) + const p1 = hexStr.indexOf(hex.charAt(i + 1)) + if (p0 < 0 || p1 < 0) + throw "Invalid hex" + res[i >> 1] = (p0 << 4) | p1 + } + return res + } + + /** + * Create a new buffer with UTF8-encoded string + * @param str the string to put in the buffer + */ + //% shim=control::createBufferFromUTF8 + export declare function fromUTF8(str: string): Buffer; + + function chunkLen(s: string, off: number, maxlen: number) { + let L = Math.idiv(maxlen, 3) + let R = maxlen + + if (fromUTF8(s.slice(off, off + R)).length <= maxlen) + return R + + while (L < R) { + const m = (L + R) >> 1 + if (m == L) + break + const ll = fromUTF8(s.slice(off, off + m)).length + if (ll <= maxlen) + L = m + else + R = m + } + + return L + } + + export function chunkedFromUTF8(str: string, maxBytes: number) { + if (maxBytes < 3) + throw "Oops" + const chunks: Buffer[] = [] + let pos = 0 + while (pos < str.length) { + const len = chunkLen(str, pos, maxBytes) + chunks.push(fromUTF8(str.slice(pos, pos + len))) + pos += len + } + return chunks + } + + /** + * Create a new buffer initialized to bytes from given array. + * @param bytes data to initialize with + */ + export function fromArray(bytes: number[]) { + let buf = Buffer.create(bytes.length) + for (let i = 0; i < bytes.length; ++i) + buf[i] = bytes[i] + return buf + } + + /** + * Concatenates all buffers in the list + */ + export function concat(buffers: Buffer[]) { + let len = 0 + for (let b of buffers) + len += b.length + const r = Buffer.create(len) + len = 0 + for (let b of buffers) { + r.write(len, b) + len += b.length + } + return r + } + + // Python-like packing, see https://docs.python.org/3/library/struct.html + + export function packedSize(format: string) { + return __packUnpackCore(format, null, null, true) + } + + export function pack(format: string, nums: number[]) { + let buf = Buffer.create(packedSize(format)) + __packUnpackCore(format, nums, buf, true) + return buf + } + + function getFormat(pychar: string, isBig: boolean) { + switch (pychar) { + case 'B': + return NumberFormat.UInt8LE + case 'b': + return NumberFormat.Int8LE + case 'H': + return isBig ? NumberFormat.UInt16BE : NumberFormat.UInt16LE + case 'h': + return isBig ? NumberFormat.Int16BE : NumberFormat.Int16LE + case 'I': + case 'L': + return isBig ? NumberFormat.UInt32BE : NumberFormat.UInt32LE + case 'i': + case 'l': + return isBig ? NumberFormat.Int32BE : NumberFormat.Int32LE + case 'f': + return isBig ? NumberFormat.Float32BE : NumberFormat.Float32LE + case 'd': + return isBig ? NumberFormat.Float64BE : NumberFormat.Float64LE + default: + return null as NumberFormat + } + } + + function isDigit(ch: string) { + const code = ch.charCodeAt(0) + return 0x30 <= code && code <= 0x39 + } + + export function __packUnpackCore(format: string, nums: number[], buf: Buffer, isPack: boolean, off = 0) { + let isBig = false + let idx = 0 + for (let i = 0; i < format.length; ++i) { + switch (format[i]) { + case ' ': + case '<': + case '=': + isBig = false + break + case '>': + case '!': + isBig = true + break + default: + const i0 = i + while (isDigit(format[i])) i++ + let reps = 1 + if (i0 != i) + reps = parseInt(format.slice(i0, i)) + if (format[i] == 'x') + off += reps + else + while (reps--) { + let fmt = getFormat(format[i], isBig) + if (fmt === null) { + control.fail("Unsupported format character: " + format[i]) + } else { + if (buf) { + if (isPack) + buf.setNumber(fmt, off, nums[idx++]) + else + nums.push(buf.getNumber(fmt, off)) + } + + off += sizeOfNumberFormat(fmt) + } + } + break + } + } + return off + } + + /** + * Get the size in bytes of specified number format. + */ + export function sizeOfNumberFormat(format: NumberFormat) { + switch (format) { + case NumberFormat.Int8LE: + case NumberFormat.UInt8LE: + case NumberFormat.Int8BE: + case NumberFormat.UInt8BE: + return 1; + case NumberFormat.Int16LE: + case NumberFormat.UInt16LE: + case NumberFormat.Int16BE: + case NumberFormat.UInt16BE: + return 2; + case NumberFormat.Int32LE: + case NumberFormat.Int32BE: + case NumberFormat.UInt32BE: + case NumberFormat.UInt32LE: + case NumberFormat.Float32BE: + case NumberFormat.Float32LE: + return 4; + case NumberFormat.Float64BE: + case NumberFormat.Float64LE: + return 8; + } + return 0; + } +} diff --git a/libs/base/configkeys.h b/libs/base/configkeys.h new file mode 100644 index 00000000..ba9544cb --- /dev/null +++ b/libs/base/configkeys.h @@ -0,0 +1,478 @@ +#ifndef __PXT_CONFIGKEYS_H +#define __PXT_CONFIGKEYS_H + +// used by pins.cpp to mask off the pin name from any config +// lower 16 pins of value are the pin name +#define CFG_PIN_NAME_MSK 0x0000ffff +// upper 16 bits of value is any configuration of the pin. +#define CFG_PIN_CONFIG_MSK 0xffff0000 + +// begin optional pin configurations +#define CFG_PIN_CONFIG_ACTIVE_LO 0x10000 + + +#define CFG_MAGIC0 0x1e9e10f1 +#define CFG_MAGIC1 0x20227a79 + +// these define keys for getConfig() function +#define CFG_PIN_ACCELEROMETER_INT 1 +#define CFG_PIN_ACCELEROMETER_SCL 2 +#define CFG_PIN_ACCELEROMETER_SDA 3 +#define CFG_PIN_BTN_A 4 +#define CFG_PIN_BTN_B 5 +#define CFG_PIN_BTN_SLIDE 6 +#define CFG_PIN_DOTSTAR_CLOCK 7 +#define CFG_PIN_DOTSTAR_DATA 8 +#define CFG_PIN_FLASH_CS 9 +#define CFG_PIN_FLASH_MISO 10 +#define CFG_PIN_FLASH_MOSI 11 +#define CFG_PIN_FLASH_SCK 12 +#define CFG_PIN_LED 13 +#define CFG_PIN_LIGHT 14 +#define CFG_PIN_MICROPHONE 15 +#define CFG_PIN_MIC_CLOCK 16 +#define CFG_PIN_MIC_DATA 17 +#define CFG_PIN_MISO 18 +#define CFG_PIN_MOSI 19 +// the preferred pin to drive an external neopixel strip +#define CFG_PIN_NEOPIXEL 20 +#define CFG_PIN_RX 21 +#define CFG_PIN_RXLED 22 +#define CFG_PIN_SCK 23 +#define CFG_PIN_SCL 24 +#define CFG_PIN_SDA 25 +#define CFG_PIN_SPEAKER_AMP 26 +#define CFG_PIN_TEMPERATURE 27 +#define CFG_PIN_TX 28 +#define CFG_PIN_TXLED 29 +#define CFG_PIN_IR_OUT 30 +#define CFG_PIN_IR_IN 31 +#define CFG_PIN_DISPLAY_SCK 32 +#define CFG_PIN_DISPLAY_MISO 33 +#define CFG_PIN_DISPLAY_MOSI 34 +#define CFG_PIN_DISPLAY_CS 35 +#define CFG_PIN_DISPLAY_DC 36 +#define CFG_DISPLAY_WIDTH 37 +#define CFG_DISPLAY_HEIGHT 38 +#define CFG_DISPLAY_CFG0 39 +#define CFG_DISPLAY_CFG1 40 +#define CFG_DISPLAY_CFG2 41 +#define CFG_DISPLAY_CFG3 42 +#define CFG_PIN_DISPLAY_RST 43 +#define CFG_PIN_DISPLAY_BL 44 +#define CFG_PIN_SERVO_1 45 +#define CFG_PIN_SERVO_2 46 +#define CFG_PIN_BTN_LEFT 47 +#define CFG_PIN_BTN_RIGHT 48 +#define CFG_PIN_BTN_UP 49 +#define CFG_PIN_BTN_DOWN 50 +#define CFG_PIN_BTN_MENU 51 +#define CFG_PIN_LED_R 52 +#define CFG_PIN_LED_G 53 +#define CFG_PIN_LED_B 54 +#define CFG_PIN_LED1 55 +#define CFG_PIN_LED2 56 +#define CFG_PIN_LED3 57 +#define CFG_PIN_LED4 58 +#define CFG_SPEAKER_VOLUME 59 + +#define CFG_PIN_JACK_TX 60 +#define CFG_PIN_JACK_SENSE 61 +#define CFG_PIN_JACK_HPEN 62 +#define CFG_PIN_JACK_BZEN 63 +#define CFG_PIN_JACK_PWREN 64 +#define CFG_PIN_JACK_SND 65 +#define CFG_PIN_JACK_BUSLED 66 +#define CFG_PIN_JACK_COMMLED 67 + +#define CFG_PIN_BTN_SOFT_RESET 69 +#define CFG_ACCELEROMETER_TYPE 70 +#define CFG_PIN_BTNMX_LATCH 71 +#define CFG_PIN_BTNMX_CLOCK 72 +#define CFG_PIN_BTNMX_DATA 73 +#define CFG_PIN_BTN_MENU2 74 +#define CFG_PIN_BATTSENSE 75 +#define CFG_PIN_VIBRATION 76 +#define CFG_PIN_PWREN 77 +#define CFG_DISPLAY_TYPE 78 + +#define CFG_PIN_ROTARY_ENCODER_A 79 +#define CFG_PIN_ROTARY_ENCODER_B 80 + +#define CFG_ACCELEROMETER_SPACE 81 + +#define CFG_PIN_WIFI_MOSI 82 +#define CFG_PIN_WIFI_MISO 83 +#define CFG_PIN_WIFI_SCK 84 +#define CFG_PIN_WIFI_TX 85 +#define CFG_PIN_WIFI_RX 86 +#define CFG_PIN_WIFI_CS 87 +#define CFG_PIN_WIFI_BUSY 88 +#define CFG_PIN_WIFI_RESET 89 +#define CFG_PIN_WIFI_GPIO0 90 +#define CFG_PIN_WIFI_AT_TX 91 +#define CFG_PIN_WIFI_AT_RX 92 + +#define CFG_PIN_USB_POWER 93 + +// default I2C address +#define ACCELEROMETER_TYPE_LIS3DH 0x32 +#define ACCELEROMETER_TYPE_LIS3DH_ALT 0x30 +#define ACCELEROMETER_TYPE_MMA8453 0x38 +#define ACCELEROMETER_TYPE_FXOS8700 0x3C +#define ACCELEROMETER_TYPE_MMA8653 0x3A +#define ACCELEROMETER_TYPE_MSA300 0x4C +#define ACCELEROMETER_TYPE_MPU6050 0x68 + +#define DISPLAY_TYPE_ST7735 7735 +#define DISPLAY_TYPE_ILI9341 9341 +#define DISPLAY_TYPE_SMART 4242 + +#define CFG_PIN_A0 100 +#define CFG_PIN_A1 101 +#define CFG_PIN_A2 102 +#define CFG_PIN_A3 103 +#define CFG_PIN_A4 104 +#define CFG_PIN_A5 105 +#define CFG_PIN_A6 106 +#define CFG_PIN_A7 107 +#define CFG_PIN_A8 108 +#define CFG_PIN_A9 109 +#define CFG_PIN_A10 110 +#define CFG_PIN_A11 111 +#define CFG_PIN_A12 112 +#define CFG_PIN_A13 113 +#define CFG_PIN_A14 114 +#define CFG_PIN_A15 115 +#define CFG_PIN_A16 116 +#define CFG_PIN_A17 117 +#define CFG_PIN_A18 118 +#define CFG_PIN_A19 119 +#define CFG_PIN_A20 120 +#define CFG_PIN_A21 121 +#define CFG_PIN_A22 122 +#define CFG_PIN_A23 123 +#define CFG_PIN_A24 124 +#define CFG_PIN_A25 125 +#define CFG_PIN_A26 126 +#define CFG_PIN_A27 127 +#define CFG_PIN_A28 128 +#define CFG_PIN_A29 129 +#define CFG_PIN_A30 130 +#define CFG_PIN_A31 131 + +#define CFG_PIN_D0 150 +#define CFG_PIN_D1 151 +#define CFG_PIN_D2 152 +#define CFG_PIN_D3 153 +#define CFG_PIN_D4 154 +#define CFG_PIN_D5 155 +#define CFG_PIN_D6 156 +#define CFG_PIN_D7 157 +#define CFG_PIN_D8 158 +#define CFG_PIN_D9 159 +#define CFG_PIN_D10 160 +#define CFG_PIN_D11 161 +#define CFG_PIN_D12 162 +#define CFG_PIN_D13 163 +#define CFG_PIN_D14 164 +#define CFG_PIN_D15 165 +#define CFG_PIN_D16 166 +#define CFG_PIN_D17 167 +#define CFG_PIN_D18 168 +#define CFG_PIN_D19 169 +#define CFG_PIN_D20 170 +#define CFG_PIN_D21 171 +#define CFG_PIN_D22 172 +#define CFG_PIN_D23 173 +#define CFG_PIN_D24 174 +#define CFG_PIN_D25 175 +#define CFG_PIN_D26 176 +#define CFG_PIN_D27 177 +#define CFG_PIN_D28 178 +#define CFG_PIN_D29 179 +#define CFG_PIN_D30 180 +#define CFG_PIN_D31 181 + +#define CFG_NUM_NEOPIXELS 200 +#define CFG_NUM_DOTSTARS 201 +#define CFG_DEFAULT_BUTTON_MODE 202 +#define CFG_SWD_ENABLED 203 +#define CFG_FLASH_BYTES 204 +#define CFG_RAM_BYTES 205 +#define CFG_SYSTEM_HEAP_BYTES 206 +#define CFG_LOW_MEM_SIMULATION_KB 207 +#define CFG_BOOTLOADER_BOARD_ID 208 +#define CFG_UF2_FAMILY 209 +#define CFG_PINS_PORT_SIZE 210 +#define CFG_BOOTLOADER_PROTECTION 211 +#define CFG_POWER_DEEPSLEEP_TIMEOUT 212 +#define CFG_ANALOG_BUTTON_THRESHOLD 213 +#define CFG_CPU_MHZ 214 +#define CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS 215 +#define CFG_ANALOG_JOYSTICK_MIN 216 +#define CFG_ANALOG_JOYSTICK_MAX 217 +#define CFG_TIMERS_TO_USE 218 +// configs to specify the onboard (built-in) dotstar or neopixel strips +// some boards have a combination of dotstar, neopixel strips like neotrellis +#define CFG_PIN_ONBOARD_DOTSTAR_CLOCK 219 +#define CFG_PIN_ONBOARD_DOTSTAR_DATA 220 +#define CFG_NUM_ONBOARD_DOTSTARS 221 +#define CFG_PIN_ONBOARD_NEOPIXEL 222 +#define CFG_NUM_ONBOARD_NEOPIXELS 223 + +#define CFG_MATRIX_KEYPAD_MESSAGE_ID 239 +#define CFG_NUM_MATRIX_KEYPAD_ROWS 240 +#define CFG_PIN_MATRIX_KEYPAD_ROW0 241 +#define CFG_PIN_MATRIX_KEYPAD_ROW1 242 +#define CFG_PIN_MATRIX_KEYPAD_ROW2 243 +#define CFG_PIN_MATRIX_KEYPAD_ROW3 244 +#define CFG_PIN_MATRIX_KEYPAD_ROW4 245 +#define CFG_PIN_MATRIX_KEYPAD_ROW5 246 +#define CFG_PIN_MATRIX_KEYPAD_ROW6 247 +#define CFG_PIN_MATRIX_KEYPAD_ROW7 248 +#define CFG_NUM_MATRIX_KEYPAD_COLS 250 +#define CFG_PIN_MATRIX_KEYPAD_COL0 251 +#define CFG_PIN_MATRIX_KEYPAD_COL1 252 +#define CFG_PIN_MATRIX_KEYPAD_COL2 253 +#define CFG_PIN_MATRIX_KEYPAD_COL3 254 +#define CFG_PIN_MATRIX_KEYPAD_COL4 255 +#define CFG_PIN_MATRIX_KEYPAD_COL5 256 +#define CFG_PIN_MATRIX_KEYPAD_COL6 257 +#define CFG_PIN_MATRIX_KEYPAD_COL7 258 + +#define CFG_PIN_B0 300 +#define CFG_PIN_B1 301 +#define CFG_PIN_B2 302 +#define CFG_PIN_B3 303 +#define CFG_PIN_B4 304 +#define CFG_PIN_B5 305 +#define CFG_PIN_B6 306 +#define CFG_PIN_B7 307 +#define CFG_PIN_B8 308 +#define CFG_PIN_B9 309 +#define CFG_PIN_B10 310 +#define CFG_PIN_B11 311 +#define CFG_PIN_B12 312 +#define CFG_PIN_B13 313 +#define CFG_PIN_B14 314 +#define CFG_PIN_B15 315 +#define CFG_PIN_B16 316 +#define CFG_PIN_B17 317 +#define CFG_PIN_B18 318 +#define CFG_PIN_B19 319 +#define CFG_PIN_B20 320 +#define CFG_PIN_B21 321 +#define CFG_PIN_B22 322 +#define CFG_PIN_B23 323 +#define CFG_PIN_B24 324 +#define CFG_PIN_B25 325 +#define CFG_PIN_B26 326 +#define CFG_PIN_B27 327 +#define CFG_PIN_B28 328 +#define CFG_PIN_B29 329 +#define CFG_PIN_B30 330 +#define CFG_PIN_B31 331 + +#define CFG_PIN_C0 350 +#define CFG_PIN_C1 351 +#define CFG_PIN_C2 352 +#define CFG_PIN_C3 353 +#define CFG_PIN_C4 354 +#define CFG_PIN_C5 355 +#define CFG_PIN_C6 356 +#define CFG_PIN_C7 357 +#define CFG_PIN_C8 358 +#define CFG_PIN_C9 359 +#define CFG_PIN_C10 360 +#define CFG_PIN_C11 361 +#define CFG_PIN_C12 362 +#define CFG_PIN_C13 363 +#define CFG_PIN_C14 364 +#define CFG_PIN_C15 365 +#define CFG_PIN_C16 366 +#define CFG_PIN_C17 367 +#define CFG_PIN_C18 368 +#define CFG_PIN_C19 369 +#define CFG_PIN_C20 370 +#define CFG_PIN_C21 371 +#define CFG_PIN_C22 372 +#define CFG_PIN_C23 373 +#define CFG_PIN_C24 374 +#define CFG_PIN_C25 375 +#define CFG_PIN_C26 376 +#define CFG_PIN_C27 377 +#define CFG_PIN_C28 378 +#define CFG_PIN_C29 379 +#define CFG_PIN_C30 380 +#define CFG_PIN_C31 381 + +#define CFG_PIN_P0 400 +#define CFG_PIN_P1 401 +#define CFG_PIN_P2 402 +#define CFG_PIN_P3 403 +#define CFG_PIN_P4 404 +#define CFG_PIN_P5 405 +#define CFG_PIN_P6 406 +#define CFG_PIN_P7 407 +#define CFG_PIN_P8 408 +#define CFG_PIN_P9 409 +#define CFG_PIN_P10 410 +#define CFG_PIN_P11 411 +#define CFG_PIN_P12 412 +#define CFG_PIN_P13 413 +#define CFG_PIN_P14 414 +#define CFG_PIN_P15 415 +#define CFG_PIN_P16 416 +#define CFG_PIN_P17 417 +#define CFG_PIN_P18 418 +#define CFG_PIN_P19 419 +#define CFG_PIN_P20 420 +#define CFG_PIN_P21 421 +#define CFG_PIN_P22 422 +#define CFG_PIN_P23 423 +#define CFG_PIN_P24 424 +#define CFG_PIN_P25 425 +#define CFG_PIN_P26 426 +#define CFG_PIN_P27 427 +#define CFG_PIN_P28 428 +#define CFG_PIN_P29 429 +#define CFG_PIN_P30 430 +#define CFG_PIN_P31 431 +#define CFG_PIN_P32 432 +#define CFG_PIN_P33 433 +#define CFG_PIN_P34 434 +#define CFG_PIN_P35 435 +#define CFG_PIN_P36 436 +#define CFG_PIN_P37 437 +#define CFG_PIN_P38 438 +#define CFG_PIN_P39 439 +#define CFG_PIN_P40 440 +#define CFG_PIN_P41 441 +#define CFG_PIN_P42 442 +#define CFG_PIN_P43 443 +#define CFG_PIN_P44 444 +#define CFG_PIN_P45 445 +#define CFG_PIN_P46 446 +#define CFG_PIN_P47 447 +#define CFG_PIN_P48 448 +#define CFG_PIN_P49 449 +#define CFG_PIN_P50 450 +#define CFG_PIN_P51 451 +#define CFG_PIN_P52 452 +#define CFG_PIN_P53 453 +#define CFG_PIN_P54 454 +#define CFG_PIN_P55 455 +#define CFG_PIN_P56 456 +#define CFG_PIN_P57 457 +#define CFG_PIN_P58 458 +#define CFG_PIN_P59 459 +#define CFG_PIN_P60 460 +#define CFG_PIN_P61 461 +#define CFG_PIN_P62 462 +#define CFG_PIN_P63 463 + +#define CFG_PIN_LORA_MISO 1001 +#define CFG_PIN_LORA_MOSI 1002 +#define CFG_PIN_LORA_SCK 1003 +#define CFG_PIN_LORA_CS 1004 +#define CFG_PIN_LORA_BOOT 1005 +#define CFG_PIN_LORA_RESET 1006 +#define CFG_PIN_IRRXLED 1007 +#define CFG_PIN_IRTXLED 1008 +#define CFG_PIN_LCD_RESET 1009 +#define CFG_PIN_LCD_ENABLE 1010 +#define CFG_PIN_LCD_DATALINE4 1011 +#define CFG_PIN_LCD_DATALINE5 1012 +#define CFG_PIN_LCD_DATALINE6 1013 +#define CFG_PIN_LCD_DATALINE7 1014 +#define CFG_NUM_LCD_COLUMNS 1015 +#define CFG_NUM_LCD_ROWS 1016 + +//RoboHAT MM1 pinout +#define CFG_PIN_RCC0 1017 +#define CFG_PIN_RCC1 1018 +#define CFG_PIN_RCC2 1019 +#define CFG_PIN_RCC3 1020 +#define CFG_PIN_RCC4 1021 +#define CFG_PIN_RCC5 1022 +#define CFG_PIN_RCC6 1023 +#define CFG_PIN_RCC7 1024 +#define CFG_PIN_SERVO0 1025 +#define CFG_PIN_SERVO1 1026 +#define CFG_PIN_SERVO2 1027 +#define CFG_PIN_SERVO3 1028 +#define CFG_PIN_SERVO4 1029 +#define CFG_PIN_SERVO5 1030 +#define CFG_PIN_SERVO6 1031 +#define CFG_PIN_SERVO7 1032 +#define CFG_PIN_SERVO8 1033 +#define CFG_PIN_PI_TX 1034 +#define CFG_PIN_PI_RX 1035 +#define CFG_PIN_GPS_SDA 1036 +#define CFG_PIN_GPS_SCL 1037 +#define CFG_PIN_GPS_TX 1038 +#define CFG_PIN_GPS_RX 1039 +#define CFG_PIN_GROVE0 1040 +#define CFG_PIN_GROVE1 1041 +#define CFG_PIN_SS 1042 + +// Adafruit Grand Central M4 +#define CFG_PIN_D33 183 +#define CFG_PIN_D34 184 +#define CFG_PIN_D35 185 +#define CFG_PIN_D36 186 +#define CFG_PIN_D37 187 +#define CFG_PIN_D38 188 +#define CFG_PIN_D39 189 +#define CFG_PIN_D40 190 +#define CFG_PIN_D41 191 +#define CFG_PIN_D42 192 +#define CFG_PIN_D43 193 +#define CFG_PIN_D44 194 +#define CFG_PIN_D45 195 +#define CFG_PIN_D46 196 +#define CFG_PIN_D47 197 +#define CFG_PIN_D48 198 +#define CFG_PIN_D49 199 +#define CFG_PIN_D50 259 +#define CFG_PIN_D51 260 +#define CFG_PIN_D52 261 +#define CFG_PIN_D53 262 + +#define CFG_PIN_TX1 263 +#define CFG_PIN_TX2 264 +#define CFG_PIN_TX3 265 +#define CFG_PIN_RX1 266 +#define CFG_PIN_RX2 267 +#define CFG_PIN_RX3 268 +#define CFG_PIN_SCL1 269 +#define CFG_PIN_SDA1 270 +#define CFG_PIN_PCC_D0 271 +#define CFG_PIN_PCC_D1 272 +#define CFG_PIN_PCC_D2 273 +#define CFG_PIN_PCC_D3 274 +#define CFG_PIN_PCC_D4 275 +#define CFG_PIN_PCC_D5 276 +#define CFG_PIN_PCC_D6 277 +#define CFG_PIN_PCC_D7 278 +#define CFG_PIN_PCC_D8 279 +#define CFG_PIN_PCC_D9 280 +#define CFG_PIN_PCC_D10 281 +#define CFG_PIN_PCC_D11 282 +#define CFG_PIN_PCC_D12 283 +#define CFG_PIN_PCC_D13 284 +#define CFG_PIN_CC_DEN1 285 +#define CFG_PIN_CC_DEN2 286 +#define CFG_PIN_CC_CLK 287 +#define CFG_PIN_XCC_CLK 288 + + +#define CFG_PIN_JDPWR_PRE_SENSE 1100 +#define CFG_PIN_JDPWR_GND_SENSE 1101 +#define CFG_PIN_JDPWR_PULSE 1102 +#define CFG_PIN_JDPWR_OVERLOAD_LED 1103 +#define CFG_PIN_JDPWR_ENABLE 1104 +#define CFG_PIN_JDPWR_FAULT 1105 + +#endif diff --git a/libs/base/console.ts b/libs/base/console.ts new file mode 100644 index 00000000..c35820c5 --- /dev/null +++ b/libs/base/console.ts @@ -0,0 +1,138 @@ +/// + +enum ConsolePriority { + Debug = 0, + Log = 1, + Warning = 2, + Error = 3, + Silent = 4 +} + +/** + * Reading and writing data to the console output. + */ +//% weight=12 color=#002050 icon="\uf120" +//% advanced=true +namespace console { + type Listener = (priority: ConsolePriority, text: string) => void; + + /** + * Minimum priority to send messages to listeners + */ + export let minPriority = ConsolePriority.Log; + + //% whenUsed + const listeners: Listener[] = [ + function (priority: ConsolePriority, text: string) { control.__log(priority, text); } + ]; + + export function add(priority: ConsolePriority, message: any) { + if (priority < minPriority) return; + let text = inspect(message); + // add new line + text += "\n"; + // send to listeners + for (let i = 0; i < listeners.length; ++i) + listeners[i](priority, text); + } + + export function debug(text: any) { + add(ConsolePriority.Debug, text); + } + + export function warn(text: any) { + add(ConsolePriority.Warning, text); + } + + export function error(text: any) { + add(ConsolePriority.Error, text); + } + + /** + * Write a line of text to the console output. + * @param value to send + */ + //% weight=90 + //% help=console/log blockGap=8 + //% blockId=console_log block="console log $value" + //% value.shadow=text + export function log(value: any): void { + add(ConsolePriority.Log, value); + } + + /** + * Write a name:value pair as a line of text to the console output. + * @param name name of the value stream, eg: "x" + * @param value to write + */ + //% weight=88 blockGap=8 + //% help=console/log-value + //% blockId=console_log_value block="console|log value %name|= %value" + //% name.shadow=text + //% value.shadow=math_number + export function logValue(name: any, value: any): void { + log(name ? `${inspect(name)}: ${inspect(value)}` : `${inspect(value)}`) + } + + /** + * Convert any object or value to a string representation + * @param obj value to be converted to a string + * @param maxElements [optional] max number values in an object to include in output + */ + export function inspect(obj: any, maxElements = 20): string { + if (typeof obj == "string") { + return obj; + } else if (typeof obj == "number") { + return "" + obj; + } else if (Array.isArray(obj)) { + const asArr = (obj as Array); + if (asArr.length <= maxElements) { + return asArr.join(","); + } else { + return `${asArr.slice(0, maxElements).join(",")}...`; + } + } else { + const asString = obj + ""; + if (asString != "[object Object]" + && asString != "[Object]") { // on arcade at least, default toString is [Object] on hardware instead of standard + return asString; + } + + let keys = Object.keys(obj); + const snipped = keys.length > maxElements; + if (snipped) { + keys = keys.slice(0, maxElements); + } + + return `{${ + keys.reduce( + (prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`, + "" + ) + (snipped ? "\n ..." : "") + } +}`; + } + } + + /** + * Adds a listener for the log messages + * @param listener + */ + //% + export function addListener(listener: (priority: ConsolePriority, text: string) => void) { + if (!listener || listeners.indexOf(listener) > -1) return; + listeners.push(listener); + } + + /** + * Removes a listener + * @param listener + */ + //% + export function removeListener(listener: (priority: ConsolePriority, text: string) => void) { + if (!listener) return; + const i = listeners.indexOf(listener); + if (i > -1) + listeners.splice(i, 1); + } +} \ No newline at end of file diff --git a/libs/base/control.cpp b/libs/base/control.cpp new file mode 100644 index 00000000..ba5733bb --- /dev/null +++ b/libs/base/control.cpp @@ -0,0 +1,103 @@ +#include "pxtbase.h" + + +namespace control { + /** + * Gets the number of milliseconds elapsed since power on. + */ + //% help=control/millis weight=50 + //% blockId=control_running_time block="millis (ms)" + int millis() { + return current_time_ms(); + } + + /** + * Gets current time in microseconds. Overflows every ~18 minutes. + */ + //% + int micros() { + return current_time_us() & 0x3fffffff; + } + + /** + * Used internally + */ + //% + void internalOnEvent(int src, int value, Action handler, int flags = 16) { + registerWithDal(src, value, handler, flags); + } + + /** + * Reset the device. + */ + //% weight=30 async help=control/reset blockGap=8 + //% blockId="control_reset" block="reset" + void reset() { + target_reset(); + } + + /** + * Block the current fiber for the given microseconds + * @param micros number of micro-seconds to wait. eg: 4 + */ + //% help=control/wait-micros weight=29 async + //% blockId="control_wait_us" block="wait (µs)%micros" + void waitMicros(int micros) { + sleep_us(micros); + } + + /** + * Run other code in the parallel. + */ + //% help=control/run-in-parallel handlerStatement=1 + //% blockId="control_run_in_parallel" block="run in parallel" blockGap=8 + void runInParallel(Action a) { + pxt::runInParallel(a); + } + + /** + * Blocks the calling thread until the specified event is raised. + */ + //% help=control/wait-for-event async + //% blockId=control_wait_for_event block="wait for event|from %src|with value %value" + void waitForEvent(int src, int value) { + pxt::waitForEvent(src, value); + } + + /** + * Derive a unique, consistent serial number of this device from internal data. + */ + //% blockId="control_device_serial_number" block="device serial number" weight=9 + //% help=control/device-serial-number + int deviceSerialNumber() { + uint64_t serial_num = pxt::getLongSerialNumber(); + return hash_fnv1(&serial_num, sizeof(serial_num)) & 0x3fffffff; + } + + /** + * Derive a unique, consistent 64-bit serial number of this device from internal data. + */ + //% blockId="control_device_long_serial_number" block="device long serial number" weight=9 + //% help=control/device-long-serial-number + Buffer deviceLongSerialNumber() { + uint64_t serial_num = pxt::getLongSerialNumber(); + return mkBuffer((uint8_t*)&serial_num, sizeof(uint64_t)); + } + + /** + * + */ + //% + void __log(int prority, String text) { + if (NULL == text) return; + pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size()); + } + + /** + * Dump internal information about a value. + */ + //% + void dmesgValue(TValue v) { + anyPrint(v); + } +} diff --git a/libs/base/control.ts b/libs/base/control.ts new file mode 100644 index 00000000..a789756d --- /dev/null +++ b/libs/base/control.ts @@ -0,0 +1,185 @@ +/** +* Program controls and events. +*/ +//% weight=90 color="#FF5722" icon="\uf110" advanced=true +namespace control { + /** + * Deprecated, use ``control.runInParallel`` instead. + */ + //% deprecated=1 hidden=1 help=control/run-in-background blockAllowMultiple=1 afterOnStart=true + //% blockId="control_run_in_background" block="run in background" blockGap=8 weight=0 + export function runInBackground(a: () => void) { + control.runInParallel(a); + } + + export const enum PXT_PANIC { + CODAL_OOM = 20, + GC_OOM = 21, + GC_TOO_BIG_ALLOCATION = 22, + CODAL_HEAP_ERROR = 30, + CODAL_NULL_DEREFERENCE = 40, + CODAL_USB_ERROR = 50, + CODAL_HARDWARE_CONFIGURATION_ERROR = 90, + + INVALID_BINARY_HEADER = 901, + OUT_OF_BOUNDS = 902, + REF_DELETED = 903, + SIZE = 904, + INVALID_VTABLE = 905, + INTERNAL_ERROR = 906, + NO_SUCH_CONFIG = 907, + NO_SUCH_PIN = 908, + INVALID_ARGUMENT = 909, + MEMORY_LIMIT_EXCEEDED = 910, + SCREEN_ERROR = 911, + MISSING_PROPERTY = 912, + INVALID_IMAGE = 913, + CALLED_FROM_ISR = 914, + HEAP_DUMPED = 915, + STACK_OVERFLOW = 916, + BLOCKING_TO_STRING = 917, + VM_ERROR = 918, + SETTINGS_CLEARED = 920, + SETTINGS_OVERLOAD = 921, + SETTINGS_SECRET_MISSING = 922, + DELETE_ON_CLASS = 923, + + CAST_FIRST = 980, + CAST_FROM_UNDEFINED = 980, + CAST_FROM_BOOLEAN = 981, + CAST_FROM_NUMBER = 982, + CAST_FROM_STRING = 983, + CAST_FROM_OBJECT = 984, + CAST_FROM_FUNCTION = 985, + CAST_FROM_NULL = 989, + + UNHANDLED_EXCEPTION = 999, + } + /** + * Display an error code and stop the program. + * @param code an error number to display. eg: 5 + */ + //% help=control/panic weight=29 + //% blockId="control_panic" block="panic %code" + //% shim=pxtrt::panic + export function panic(code: number) { } + + /** + * Display an error code and stop the program when the assertion is `false`. + */ + //% help=control/assert weight=30 + //% blockId="control_assert" block="assert %cond|with value %code" + export function assert(cond: boolean, code: number) { + if (!cond) { + fail("Assertion failed, code=" + code) + } + } + + export function fail(message: string) { + console.log("Fatal failure: ") + console.log(message) + dmesg(message) + panic(108) + } + + export class AnimationQueue { + running: boolean; + eventID: number; + public interval: number; + + constructor() { + this.running = false; + this.eventID = control.allocateNotifyEvent(); + this.interval = 1; + } + + /** + * Runs 'render' in a loop until it returns false or the 'stop' function is called + */ + runUntilDone(render: () => boolean) { + const evid = this.eventID; + + // if other animation, wait for turn + if (this.running) + control.waitForEvent(DAL.DEVICE_ID_NOTIFY, evid); + + // check if the animation hasn't been cancelled since we've waiting + if (this.isCancelled(evid)) + return; + + // run animation + this.running = true; + while (this.running + && !this.isCancelled(evid) + && render()) { + pause(this.interval); + } + + // check if the animation hasn't been cancelled since we've been waiting + if (this.isCancelled(evid)) + return; + + // we're done + this.running = false; + // unblock 1 fiber + control.raiseEvent(DAL.DEVICE_ID_NOTIFY_ONE, this.eventID); + } + + isCancelled(evid: number) { + return this.eventID !== evid; + } + + /** + * Cancels the current running animation and clears the queue + */ + cancel() { + if (this.running) { + this.running = false; + const evid = this.eventID; + this.eventID = control.allocateNotifyEvent(); + // unblock fibers + control.raiseEvent(DAL.DEVICE_ID_NOTIFY, evid); + } + } + } + + //% shim=pxt::getConfig + export declare function getConfigValue(key: int32, defl: int32): number; + + //% shim=pxt::programHash + export declare function programHash(): number; + + //% shim=pxt::programName + export declare function programName(): string; + + //% shim=control::_ramSize + function _ramSize() { + return 32 * 1024 * 1024; + } + + /** Returns estimated size of memory in bytes. */ + export function ramSize() { + return getConfigValue(DAL.CFG_RAM_BYTES, 0) || _ramSize(); + } + + /** Runs the function and returns run time in microseconds. */ + export function benchmark(f: () => void) { + const t0 = micros() + f() + let t = micros() - t0 + if (t < 0) + t += 0x3fffffff + return t + } +} + +/** + * Convert any value to text + * @param value value to be converted to text + */ +//% help=text/convert-to-text weight=1 +//% block="convert $value=math_number to text" +//% blockId=variable_to_text blockNamespace="text" +function convertToText(value: any): string { + return "" + value; +} diff --git a/libs/base/controlgc.cpp b/libs/base/controlgc.cpp new file mode 100644 index 00000000..b5a621a8 --- /dev/null +++ b/libs/base/controlgc.cpp @@ -0,0 +1,50 @@ +#include "pxtbase.h" + + +namespace control { + /** + * Force GC and dump basic information about heap. + */ + //% + void gc() { + pxt::gc(1); + } + + /** + * Force GC and halt waiting for debugger to do a full heap dump. + */ + //% + void heapDump() { + pxt::gc(2); + target_panic(PANIC_HEAP_DUMPED); + } + + + /** + * Set flags used when connecting an external debugger. + */ + //% + void setDebugFlags(int flags) { + debugFlags = flags; + } + + /** + * Record a heap snapshot to debug memory leaks. + */ + //% + void heapSnapshot() { + // only in JS backend for now + } + + /** + * Return true if profiling is enabled in the current build. + */ + //% + bool profilingEnabled() { +#ifdef PXT_PROFILE + return true; +#else + return false; +#endif + } +} diff --git a/libs/base/controlmessage.ts b/libs/base/controlmessage.ts new file mode 100644 index 00000000..d265ea5c --- /dev/null +++ b/libs/base/controlmessage.ts @@ -0,0 +1,41 @@ +namespace control.simmessages { + // these events are raised by JS simulator when messages come in + export const CONTROL_MESSAGE_EVT_ID = 2999; + export const CONTROL_MESSAGE_RECEIVED = 1; + + //% shim=pxt::sendMessage + export declare function send(channel: string, message: Buffer, parentOnly?: boolean) : void; + + //% shim=pxt::peekMessageChannel + declare function peekMessageChannel(): string; + + //% shim=pxt::readMessageData + declare function readMessageData(): Buffer; + + let handlers: { [channel: string] : (msg: Buffer) => void} + function consumeMessages() { + while(true) { + // peek channel of next message + const channel = peekMessageChannel(); + if (!channel) break; + // read next message + const msg = readMessageData(); + // send to handler + const handler = handlers && handlers[channel]; + if (handler) + handler(msg); + } + } + + /** + * Registers the handler for a message on a given channel + **/ + export function onReceived(channel: string, handler: (msg: Buffer) => void) { + if (!channel) return; + + if (!handlers) + handlers = {}; + handlers[channel] = handler; + control.onEvent(CONTROL_MESSAGE_EVT_ID, CONTROL_MESSAGE_RECEIVED, consumeMessages); + } +} \ No newline at end of file diff --git a/libs/base/core.cpp b/libs/base/core.cpp new file mode 100644 index 00000000..cd30fe50 --- /dev/null +++ b/libs/base/core.cpp @@ -0,0 +1,2029 @@ +#include "pxtbase.h" +#include +#include + +using namespace std; + +#define p10(v) __builtin_powi(10, v) + +// try not to create cons-strings shorter than this +#define SHORT_CONCAT_STRING 50 + +namespace pxt { + +PXT_DEF_STRING(emptyString, "") + +static HandlerBinding *handlerBindings; + +HandlerBinding *nextBinding(HandlerBinding *curr, int source, int value) { + for (auto p = curr; p; p = p->next) { + // DEVICE_ID_ANY == DEVICE_EXT_ANY == 0 + if ((p->source == source || p->source == 0) && + (value == -1 || p->value == value || p->value == 0)) { + return p; + } + } + return 0; +} + +HandlerBinding *findBinding(int source, int value) { + return nextBinding(handlerBindings, source, value); +} + +void setBinding(int source, int value, Action act) { + HandlerBinding *curr = NULL; + for (auto p = handlerBindings; p; p = p->next) { + if ((p->source == source) && (p->value == value)) { + curr = p; + break; + } + } + if (curr) { + curr->action = act; + return; + } + curr = new (app_alloc(sizeof(HandlerBinding))) HandlerBinding(); + curr->next = handlerBindings; + curr->source = source; + curr->value = value; + curr->action = act; + registerGC(&curr->action); + handlerBindings = curr; +} + +void coreReset() { + // these are allocated on GC heap, so they will go away together with the reset + handlerBindings = NULL; +} + +struct EmptyBufferLayout { + const void *vtable; + // data needs to be word-aligned, so we use 32 bits for length + int length; + uint8_t data[1]; +}; + +static const EmptyBufferLayout emptyBuffer[1] = {{&pxt::buffer_vt, 0, {0}}}; + +#if PXT_UTF8 +int utf8Len(const char *data, int size) { + int len = 0; + for (int i = 0; i < size; ++i) { + char c = data[i]; + len++; + if ((c & 0x80) == 0x00) { + // skip + } else if ((c & 0xe0) == 0xc0) { + i++; + } else if ((c & 0xf0) == 0xe0) { + i += 2; + } else { + // error; just skip + } + } + return len; +} + +const char *utf8Skip(const char *data, int size, int skip) { + int len = 0; + for (int i = 0; i <= size; ++i) { + char c = data[i]; + len++; + if (len > skip) + return data + i; + if ((c & 0x80) == 0x00) { + // skip + } else if ((c & 0xe0) == 0xc0) { + i++; + } else if ((c & 0xf0) == 0xe0) { + i += 2; + } else { + // error; just skip over + } + } + return NULL; +} + +static char *write3byte(char *dst, uint32_t charCode) { + if (dst) { + *dst++ = 0xe0 | (charCode >> 12); + *dst++ = 0x80 | (0x3f & (charCode >> 6)); + *dst++ = 0x80 | (0x3f & (charCode >> 0)); + } + return dst; +} + +static char *write2byte(char *dst, uint32_t charCode) { + if (dst) { + *dst++ = 0xc0 | (charCode >> 6); + *dst++ = 0x80 | (0x3f & charCode); + } + return dst; +} + +static int utf8canon(char *dst, const char *data, int size) { + int outsz = 0; + for (int i = 0; i < size;) { + uint8_t c = data[i]; + uint32_t charCode = c; + if ((c & 0x80) == 0x00) { + charCode = c; + i++; + } else if ((c & 0xe0) == 0xc0 && i + 1 < size && (data[i + 1] & 0xc0) == 0x80) { + charCode = ((c & 0x1f) << 6) | (data[i + 1] & 0x3f); + if (charCode < 0x80) + goto error; + else + i += 2; + } else if ((c & 0xf0) == 0xe0 && i + 2 < size && (data[i + 1] & 0xc0) == 0x80 && + (data[i + 2] & 0xc0) == 0x80) { + charCode = ((c & 0x0f) << 12) | (data[i + 1] & 0x3f) << 6 | (data[i + 2] & 0x3f); + // don't exclude surrogate pairs, since we're generating them + if (charCode < 0x800 /*|| (0xd800 <= charCode && charCode <= 0xdfff)*/) + goto error; + else + i += 3; + } else if ((c & 0xf8) == 0xf0 && i + 3 < size && (data[i + 1] & 0xc0) == 0x80 && + (data[i + 2] & 0xc0) == 0x80 && (data[i + 3] & 0xc0) == 0x80) { + charCode = ((c & 0x07) << 18) | (data[i + 1] & 0x3f) << 12 | (data[i + 2] & 0x3f) << 6 | + (data[i + 3] & 0x3f); + if (charCode < 0x10000 || charCode > 0x10ffff) + goto error; + else + i += 4; + } else { + goto error; + } + + if (charCode < 0x80) { + outsz += 1; + if (dst) + *dst++ = charCode; + } else if (charCode < 0x800) { + outsz += 2; + dst = write2byte(dst, charCode); + } else if (charCode < 0x10000) { + outsz += 3; + dst = write3byte(dst, charCode); + } else { + outsz += 6; // a surrogate pair + charCode -= 0x10000; + dst = write3byte(dst, 0xd800 + (charCode >> 10)); + dst = write3byte(dst, 0xdc00 + (charCode & 0x3ff)); + } + + continue; + + error: + i++; + outsz += 2; + dst = write2byte(dst, c); + } + return outsz; +} + +static int utf8CharCode(const char *data) { + unsigned char c = *data; + if ((c & 0x80) == 0) { + return c; + } else if ((c & 0xe0) == 0xc0) { + return ((c & 0x1f) << 6) | (data[1] & 0x3f); + } else if ((c & 0xf0) == 0xe0) { + return ((c & 0x0f) << 12) | (data[1] & 0x3f) << 6 | (data[2] & 0x3f); + } else { + return c; // error + } +} + +static bool isUTF8(const char *data, int len) { + for (int i = 0; i < len; ++i) { + if (data[i] & 0x80) + return true; + } + return false; +} + +static void setupSkipList(String r, const char *data, int packed) { + char *dst = (char *)(packed ? PXT_SKIP_DATA_PACK(r) : PXT_SKIP_DATA_IND(r)); + auto len = r->skip.size; + if (data) + memcpy(dst, data, len); + dst[len] = 0; + const char *ptr = dst; + auto skipEntries = PXT_NUM_SKIP_ENTRIES(r); + auto lst = packed ? r->skip_pack.list : r->skip.list; + for (int i = 0; i < skipEntries; ++i) { + ptr = utf8Skip(ptr, (int)(len - (ptr - dst)), PXT_STRING_SKIP_INCR); + if (!ptr) + oops(80); + lst[i] = ptr - dst; + } +} +#endif + +String mkStringCore(const char *data, int len) { + if (len < 0) + len = (int)strlen(data); + if (len == 0) + return (String)emptyString; + + auto vt = &string_inline_ascii_vt; + String r; + +#if PXT_UTF8 + if (data && isUTF8(data, len)) { + vt = len >= PXT_STRING_MIN_SKIP ? &string_skiplist16_packed_vt : &string_inline_utf8_vt; + } + if (vt == &string_skiplist16_packed_vt) { + int ulen = utf8Len(data, len); + r = new (gcAllocate(sizeof(void *) + 2 + 2 + (ulen / PXT_STRING_SKIP_INCR) * 2 + len + 1)) + BoxedString(vt); + r->skip_pack.size = len; + r->skip_pack.length = ulen; + setupSkipList(r, data, 1); + } else +#endif + { + // for ASCII and UTF8 the layout is the same + r = new (gcAllocate(sizeof(void *) + 2 + len + 1)) BoxedString(vt); + r->ascii.length = len; + if (data) + memcpy(r->ascii.data, data, len); + r->ascii.data[len] = 0; + } + + MEMDBG("mkString: len=%d => %p", len, r); + return r; +} + +String mkString(const char *data, int len) { +#if PXT_UTF8 + if (len < 0) + len = (int)strlen(data); + if (len == 0) + return (String)emptyString; + + int sz = utf8canon(NULL, data, len); + if (sz == len) + return mkStringCore(data, len); + // this could be optimized, but it only kicks in when the string isn't valid utf8 + // (or we need to introduce surrogate pairs) which is unlikely to be performance critical + char *tmp = (char *)app_alloc(sz); + utf8canon(tmp, data, len); + auto r = mkStringCore(tmp, sz); + app_free(tmp); + return r; +#else + return mkStringCore(data, len); +#endif +} + +#if PXT_UTF8 +// This converts surrogate pairs, which are encoded as 2 characters of 3 bytes each +// into a proper 4 byte utf-8 character. +uint32_t toRealUTF8(String str, uint8_t *dst) { + auto src = str->getUTF8Data(); + auto len = str->getUTF8Size(); + auto dlen = 0; + + for (unsigned i = 0; i < len; ++i) { + if ((uint8_t)src[i] == 0xED && i + 5 < len) { + auto c0 = utf8CharCode(src + i); + auto c1 = utf8CharCode(src + i + 3); + if (0xd800 <= c0 && c0 < 0xdc00 && 0xdc00 <= c1 && c1 < 0xe000) { + i += 5; + auto charCode = ((c0 - 0xd800) << 10) + (c1 - 0xdc00) + 0x10000; + if (dst) { + dst[dlen] = 0xf0 | (charCode >> 18); + dst[dlen + 1] = 0x80 | (0x3f & (charCode >> 12)); + dst[dlen + 2] = 0x80 | (0x3f & (charCode >> 6)); + dst[dlen + 3] = 0x80 | (0x3f & (charCode >> 0)); + } + dlen += 4; + } + } else { + if (dst) + dst[dlen] = src[i]; + dlen++; + } + } + return dlen; +} +#endif + +Buffer mkBuffer(const void *data, int len) { + if (len <= 0) + return (Buffer)emptyBuffer; + Buffer r = new (gcAllocate(sizeof(BoxedBuffer) + len)) BoxedBuffer(); + r->length = len; + if (data) + memcpy(r->data, data, len); + else + memset(r->data, 0, len); + MEMDBG("mkBuffer: len=%d => %p", len, r); + return r; +} + +static unsigned random_value = 0xC0DA1; + +//% +void seedRandom(unsigned seed) { + random_value = seed; +} + +//% expose +void seedAddRandom(unsigned seed) { + random_value ^= 0xCA2557CB * seed; +} + +unsigned getRandom(unsigned max) { + unsigned m, result; + + do { + m = (unsigned)max; + result = 0; + + do { + // Cycle the LFSR (Linear Feedback Shift Register). + // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here + // (a true legend in the field!), + // For those interested, it's documented in his paper: + // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent + // generator for 32-bit Microprocessors" + // https://www.schneier.com/paper-pseudorandom-sequence.html + unsigned r = random_value; + + r = ((((r >> 31) ^ (r >> 6) ^ (r >> 4) ^ (r >> 2) ^ (r >> 1) ^ r) & 1) << 31) | + (r >> 1); + + random_value = r; + + result = ((result << 1) | (r & 0x00000001)); + } while (m >>= 1); + } while (result > (unsigned)max); + + return result; +} + +TNumber BoxedString::charCodeAt(int pos) { +#if PXT_UTF8 + auto ptr = this->getUTF8DataAt(pos); + if (!ptr) + return TAG_NAN; + auto code = utf8CharCode(ptr); + if (!code && ptr == this->getUTF8Data() + this->getUTF8Size()) + return TAG_NAN; + return fromInt(code); +#else + if (0 <= pos && pos < this->ascii.length) { + return fromInt(this->ascii.data[pos]); + } else { + return TAG_NAN; + } +#endif +} + +PXT_DEF_STRING(sTrue, "true") +PXT_DEF_STRING(sFalse, "false") +PXT_DEF_STRING(sUndefined, "undefined") +PXT_DEF_STRING(sNull, "null") +PXT_DEF_STRING(sObject, "[Object]") +PXT_DEF_STRING(sFunction, "[Function]") +PXT_DEF_STRING(sNaN, "NaN") +PXT_DEF_STRING(sInf, "Infinity") +PXT_DEF_STRING(sMInf, "-Infinity") +} // namespace pxt + +#ifndef X86_64 + +namespace String_ { + +//% +String mkEmpty() { + return (String)emptyString; +} + +// TODO support var-args somehow? + +//% +String fromCharCode(int code) { +#if PXT_UTF8 + char buf[3]; + int len; + code &= 0xffff; // JS semantics + if (code < 0x80) { + buf[0] = code; + len = 1; + } else if (code < 0x800) { + buf[0] = 0xc0 | (code >> 6); + buf[1] = 0x80 | ((code >> 0) & 0x3f); + len = 2; + } else { + buf[0] = 0xe0 | (code >> 12); + buf[1] = 0x80 | ((code >> 6) & 0x3f); + buf[2] = 0x80 | ((code >> 0) & 0x3f); + len = 3; + } + return mkStringCore(buf, len); +#else + char buf[] = {(char)code, 0}; + return mkStringCore(buf, 1); +#endif +} + +//% +TNumber charCodeAt(String s, int pos) { + if (!s) + return TAG_NAN; + return s->charCodeAt(pos); +} + +//% +String charAt(String s, int pos) { + auto v = charCodeAt(s, pos); + if (v == TAG_NAN) + return mkEmpty(); + if (!isInt(v)) + oops(81); + return fromCharCode(numValue(v)); +} + +#define IS_CONS(s) ((s)->vtable == &string_cons_vt) +#define IS_EMPTY(s) ((s) == (String)emptyString) + +//% +String concat(String s, String other) { + if (!s) + s = (String)sNull; + if (!other) + other = (String)sNull; + if (IS_EMPTY(s)) + return other; + if (IS_EMPTY(other)) + return s; + + uint32_t lenA, lenB; + +#if PXT_UTF8 + if (IS_CONS(s)) { + // (s->cons.left + s->cons.right) + other = s->cons.left + (s->cons.right + other) + if (IS_CONS(other) || IS_CONS(s->cons.right)) + goto mkCons; + auto lenAR = s->cons.right->getUTF8Size(); + lenB = other->getUTF8Size(); + if (lenAR + lenB > SHORT_CONCAT_STRING) + goto mkCons; + // if (s->cons.right + other) is short enough, use associativity + // to construct a shallower tree; this should keep the live set reasonable + // when someone decides to construct a long string by concatenating + // single characters + + // allocate [r] first, and keep it alive + String r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt); + registerGCObj(r); + r->cons.left = s->cons.left; + // this concat() might trigger GC + r->cons.right = concat(s->cons.right, other); + unregisterGCObj(r); + return r; + } +#endif + + lenA = s->getUTF8Size(); + lenB = other->getUTF8Size(); +#if PXT_UTF8 + if (lenA + lenB > SHORT_CONCAT_STRING) + goto mkCons; +#endif + String r; + { + auto dataA = s->getUTF8Data(); + auto dataB = other->getUTF8Data(); + r = mkStringCore(NULL, lenA + lenB); + auto dst = (char *)r->getUTF8Data(); + memcpy(dst, dataA, lenA); + memcpy(dst + lenA, dataB, lenB); +#if PXT_UTF8 + if (isUTF8(dst, lenA + lenB)) + r->vtable = &string_inline_utf8_vt; +#endif + return r; + } + +#if PXT_UTF8 +mkCons: + r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt); + r->cons.left = s; + r->cons.right = other; + return r; +#endif +} + +int compare(String a, String b) { + if (a == b) + return 0; + + auto lenA = a->getUTF8Size(); + auto lenB = b->getUTF8Size(); + auto dataA = a->getUTF8Data(); + auto dataB = b->getUTF8Data(); + auto len = lenA < lenB ? lenA : lenB; + + // this also works for UTF8, provided canonical encoding + // which is guaranteed by the constructor + for (unsigned i = 0; i <= len; ++i) { + unsigned char cA = dataA[i]; + unsigned char cB = dataB[i]; + if (cA == cB) + continue; + return cA < cB ? -1 : 1; + } + return 0; +} + +//% +int length(String s) { + return s->getLength(); +} + +#define isspace(c) ((c) == ' ') +#define iswhitespace(c) \ + ((c) == 0x09 || (c) == 0x0B || (c) == 0x0C || (c) == 0x20 || (uint8_t)(c) == 0xA0 || \ + (c) == 0x0A || (c) == 0x0D) + +NUMBER mystrtod(const char *p, char **endp) { + while (iswhitespace(*p)) + p++; + NUMBER m = 1; + NUMBER v = 0; + int dot = 0; + int hasDigit = 0; + if (*p == '+') + p++; + if (*p == '-') { + m = -1; + p++; + } + + while (*p) { + int c = *p - '0'; + if (0 <= c && c <= 9) { + v *= 10; + v += c; + if (dot) + m /= 10; + hasDigit = 1; + } else if (!dot && *p == '.') { + dot = 1; + } else if (!hasDigit) { + return NAN; + } else { + break; + } + p++; + } + + v *= m; + + if (*p == 'e' || *p == 'E') { + p++; + int pw = (int)strtol(p, endp, 10); + v *= p10(pw); + } else { + *endp = (char *)p; + } + + return v; +} + +//% +TNumber toNumber(String s) { + // JSCHECK + char *endptr; + auto data = s->getUTF8Data(); + NUMBER v = mystrtod(data, &endptr); + if (v == 0.0 || v == -0.0) { + // nothing + } else if (!isnormal(v)) + v = NAN; + return fromDouble(v); +} + +//% +String substr(String s, int start, int length) { + if (length <= 0) + return mkEmpty(); + auto slen = (int)s->getLength(); + if (start < 0) + start = max(slen + start, 0); + length = min(length, slen - start); + if (length <= 0) + return mkEmpty(); + auto p = s->getUTF8DataAt(start); +#if PXT_UTF8 + auto ep = s->getUTF8DataAt(start + length); + if (ep == NULL) + oops(82); + return mkStringCore(p, (int)(ep - p)); +#else + return mkStringCore(p, length); +#endif +} + +//% +int indexOf(String s, String searchString, int start) { + if (!s || !searchString) + return -1; + + if (start < 0) + start = 0; + + auto dataA0 = s->getUTF8Data(); + auto dataA = s->getUTF8DataAt(start); + auto offset = dataA - dataA0; + auto lenA = s->getUTF8Size() - offset; + auto lenB = searchString->getUTF8Size(); + + if (dataA == NULL || lenB > lenA) + return -1; + + auto dataB = searchString->getUTF8Data(); + auto firstB = dataB[0]; + while (lenA >= lenB) { + if (*dataA == firstB && !memcmp(dataA, dataB, lenB)) +#if PXT_UTF8 + return utf8Len(dataA0, (int)(dataA - dataA0)); +#else + return dataA - dataA0; +#endif + dataA++; + lenA--; + } + return -1; +} + +//% +int includes(String s, String searchString, int start) { + return -1 != indexOf(s, searchString, start); +} + +} // namespace String_ + +namespace Boolean_ { +//% +bool bang(bool v) { + return v == 0; +} +} // namespace Boolean_ + +namespace pxt { + +// ES5 9.5, 9.6 +unsigned toUInt(TNumber v) { + if (isInt(v)) + return numValue(v); + if (isSpecial(v)) { + if ((intptr_t)v >> 6) + return 1; + else + return 0; + } + if (!v) + return 0; + + NUMBER num = toDouble(v); + if (!isnormal(num)) + return 0; +#ifdef PXT_USE_FLOAT + float rem = fmodf(truncf(num), 4294967296.0); +#else + double rem = fmod(trunc(num), 4294967296.0); +#endif + if (rem < 0.0) + rem += 4294967296.0; + return (unsigned)rem; +} +int toInt(TNumber v) { + return (int)toUInt(v); +} + +NUMBER toDouble(TNumber v) { + if (v == TAG_NAN || v == TAG_UNDEFINED) + return NAN; + if (isTagged(v)) + return toInt(v); + +#ifdef PXT64 + if (isDouble(v)) + return doubleVal(v); +#endif + + ValType t = valType(v); + +#ifndef PXT64 + if (t == ValType::Number) { + BoxedNumber *p = (BoxedNumber *)v; + return p->num; + } +#endif + + if (t == ValType::String) { + // TODO avoid allocation + auto tmp = String_::toNumber((String)v); + auto r = toDouble(tmp); + return r; + } else { + return NAN; + } +} + +float toFloat(TNumber v) { + if (v == TAG_NAN || v == TAG_UNDEFINED) + return NAN; + // optimize for the int case - this will avoid software conversion when FPU is present + if (isTagged(v)) + return toInt(v); + return (float)toDouble(v); +} + +#if !defined(PXT_HARD_FLOAT) && !defined(PXT_USE_FLOAT) +union NumberConv { + double v; + struct { + uint32_t word0; + uint32_t word1; + }; +}; + +static inline TValue doubleToInt(double x) { + NumberConv cnv; + cnv.v = x; + + if (cnv.word1 == 0 && cnv.word0 == 0) + return TAG_NUMBER(0); + + auto ex = (int)((cnv.word1 << 1) >> 21) - 1023; + + // DMESG("v=%d/1000 %p %p %d", (int)(x * 1000), cnv.word0, cnv.word1, ex); + + if (ex < 0 || ex > 29) { + // the 'MININT' case + if (ex == 30 && cnv.word0 == 0 && cnv.word1 == 0xC1D00000) + return (TValue)(0x80000001); + return NULL; + } + + int32_t r; + + if (ex <= 20) { + if (cnv.word0) + return TAG_UNDEFINED; + if (cnv.word1 << (ex + 12)) + return TAG_UNDEFINED; + r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11); + } else { + if (cnv.word0 << (ex - 20)) + return TAG_UNDEFINED; + r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11); + r |= cnv.word0 >> (32 - (ex - 20)); + } + + if (cnv.word1 >> 31) + return TAG_NUMBER(-r); + else + return TAG_NUMBER(r); +} +#else +static inline TValue doubleToInt(NUMBER r) { +#ifdef PXT64 + if ((int)r == r) + return TAG_NUMBER((int)r); +#else + int ri = ((int)r) << 1; + if ((ri >> 1) == r) + return (TNumber)(uintptr_t)(ri | 1); +#endif + return TAG_UNDEFINED; +} +#endif + +TNumber fromDouble(NUMBER r) { +#ifndef PXT_BOX_DEBUG + auto i = doubleToInt(r); + if (i) + return i; +#endif + if (isnan(r)) + return TAG_NAN; +#ifdef PXT64 + return tvalueFromDouble(r); +#else + BoxedNumber *p = NEW_GC(BoxedNumber); + p->num = r; + MEMDBG("mkNum: %d/1000 => %p", (int)(r * 1000), p); + return (TNumber)p; +#endif +} + +TNumber fromFloat(float r) { + // TODO optimize + return fromDouble(r); +} + +TNumber fromInt(int v) { + if (canBeTagged(v)) + return TAG_NUMBER(v); + return fromDouble(v); +} + +TNumber fromUInt(unsigned v) { +#ifndef PXT_BOX_DEBUG + if (v <= 0x3fffffff) + return TAG_NUMBER(v); +#endif + return fromDouble(v); +} + +TValue fromBool(bool v) { + if (v) + return TAG_TRUE; + else + return TAG_FALSE; +} + +TNumber eqFixup(TNumber v) { + if (v == TAG_NULL) + return TAG_UNDEFINED; + if (v == TAG_TRUE) + return TAG_NUMBER(1); + if (v == TAG_FALSE) + return TAG_NUMBER(0); + return v; +} + +static inline bool eq_core(TValue a, TValue b, ValType ta) { +#ifndef PXT_BOX_DEBUG + auto aa = (intptr_t)a; + auto bb = (intptr_t)b; + + // if at least one of the values is tagged, they are not equal + if ((aa | bb) & 3) + return false; +#endif + + if (ta == ValType::String) + return String_::compare((String)a, (String)b) == 0; + else if (ta == ValType::Number) + return toDouble(a) == toDouble(b); + else + return a == b; +} + +bool eqq_bool(TValue a, TValue b) { + if (a == TAG_NAN || b == TAG_NAN) + return false; + + if (a == b) + return true; + + if (bothNumbers(a, b)) + return false; + + ValType ta = valType(a); + ValType tb = valType(b); + + if (ta != tb) + return false; + + return eq_core(a, b, ta); +} + +bool eq_bool(TValue a, TValue b) { + if (a == TAG_NAN || b == TAG_NAN) + return false; + + if (eqFixup(a) == eqFixup(b)) + return true; + + if (bothNumbers(a, b)) + return false; + + ValType ta = valType(a); + ValType tb = valType(b); + + if ((ta == ValType::String && tb == ValType::Number) || + (tb == ValType::String && ta == ValType::Number)) + return toDouble(a) == toDouble(b); + + if (ta == ValType::Boolean) { + a = eqFixup(a); + ta = ValType::Number; + } + if (tb == ValType::Boolean) { + b = eqFixup(b); + tb = ValType::Number; + } + + if (ta != tb) + return false; + + return eq_core(a, b, ta); +} + +// TODO move to assembly +//% +bool switch_eq(TValue a, TValue b) { + if (eq_bool(a, b)) { + return true; + } + return false; +} + +} // namespace pxt + +#define NUMOP(op) return fromDouble(toDouble(a) op toDouble(b)); +#define BITOP(op) return fromInt(toInt(a) op toInt(b)); +namespace numops { + +int toBool(TValue v) { + if (isTagged(v)) { + if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NAN || v == TAG_NULL || + v == TAG_NUMBER(0)) + return 0; + else + return 1; + } + + ValType t = valType(v); + if (t == ValType::String) { + String s = (String)v; + if (IS_EMPTY(s)) + return 0; + } else if (t == ValType::Number) { + auto x = toDouble(v); + if (isnan(x) || x == 0.0 || x == -0.0) + return 0; + else + return 1; + } + + return 1; +} + +int toBoolDecr(TValue v) { + if (v == TAG_TRUE) + return 1; + if (v == TAG_FALSE) + return 0; + return toBool(v); +} + +// The integer, non-overflow case for add/sub/bit opts is handled in assembly + +#ifdef PXT_VM +#define NUMOP2(op) \ + if (bothNumbers(a, b)) { \ + auto tmp = (int64_t)numValue(a) op(int64_t) numValue(b); \ + if ((int)tmp == tmp) \ + return TAG_NUMBER((int)tmp); \ + } \ + NUMOP(op) +#else +#define NUMOP2(op) NUMOP(op) +#endif + +//% +TNumber adds(TNumber a, TNumber b){NUMOP2(+)} + +//% +TNumber subs(TNumber a, TNumber b){NUMOP2(-)} + +//% +TNumber muls(TNumber a, TNumber b) { + if (bothNumbers(a, b)) { +#ifdef PXT64 + auto tmp = (int64_t)numValue(a) * (int64_t)numValue(b); + if ((int)tmp == tmp) + return TAG_NUMBER((int)tmp); +#else + int aa = (int)a; + int bb = (int)b; + // if both operands fit 15 bits, the result will not overflow int + if ((aa >> 15 == 0 || aa >> 15 == -1) && (bb >> 15 == 0 || bb >> 15 == -1)) { + // it may overflow 31 bit int though - use fromInt to convert properly + return fromInt((aa >> 1) * (bb >> 1)); + } +#endif + } + NUMOP(*) +} + +//% +TNumber div(TNumber a, TNumber b) { + if (b == TAG_NUMBER(1)) + return a; + NUMOP(/) +} + +//% +TNumber mod(TNumber a, TNumber b) { + if (isInt(a) && isInt(b) && numValue(b)) + BITOP(%) + return fromDouble(fmod(toDouble(a), toDouble(b))); +} + +//% +TNumber lsls(TNumber a, TNumber b) { + return fromInt(toInt(a) << (toInt(b) & 0x1f)); +} + +//% +TNumber lsrs(TNumber a, TNumber b) { + return fromUInt(toUInt(a) >> (toUInt(b) & 0x1f)); +} + +//% +TNumber asrs(TNumber a, TNumber b) { + return fromInt(toInt(a) >> (toInt(b) & 0x1f)); +} + +//% +TNumber eors(TNumber a, TNumber b){BITOP(^)} + +//% +TNumber orrs(TNumber a, TNumber b){BITOP(|)} + +//% +TNumber bnot(TNumber a) { + return fromInt(~toInt(a)); +} + +//% +TNumber ands(TNumber a, TNumber b) { + BITOP(&) +} + +#ifdef PXT64 +#define CMPOP_RAW(op, t, f) \ + if (bothNumbers(a, b)) \ + return numValue(a) op numValue(b) ? t : f; \ + int cmp = valCompare(a, b); \ + return cmp != -2 && cmp op 0 ? t : f; +#else +#define CMPOP_RAW(op, t, f) \ + if (bothNumbers(a, b)) \ + return (intptr_t)a op((intptr_t)b) ? t : f; \ + int cmp = valCompare(a, b); \ + return cmp != -2 && cmp op 0 ? t : f; +#endif + +#define CMPOP(op) CMPOP_RAW(op, TAG_TRUE, TAG_FALSE) + +// 7.2.13 Abstract Relational Comparison +static int valCompare(TValue a, TValue b) { + if (a == TAG_NAN || b == TAG_NAN) + return -2; + + ValType ta = valType(a); + ValType tb = valType(b); + + if (ta == ValType::String && tb == ValType::String) + return String_::compare((String)a, (String)b); + + if (a == b) + return 0; + + auto da = toDouble(a); + auto db = toDouble(b); + + if (isnan(da) || isnan(db)) + return -2; + + if (da < db) + return -1; + else if (da > db) + return 1; + else + return 0; +} + +//% +bool lt_bool(TNumber a, TNumber b){CMPOP_RAW(<, true, false)} + +//% +TNumber le(TNumber a, TNumber b){CMPOP(<=)} + +//% +TNumber lt(TNumber a, TNumber b){CMPOP(<)} + +//% +TNumber ge(TNumber a, TNumber b){CMPOP(>=)} + +//% +TNumber gt(TNumber a, TNumber b){CMPOP(>)} + +//% +TNumber eq(TNumber a, TNumber b) { + return pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; +} + +//% +TNumber neq(TNumber a, TNumber b) { + return !pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; +} + +//% +TNumber eqq(TNumber a, TNumber b) { + return pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; +} + +//% +TNumber neqq(TNumber a, TNumber b) { + return !pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; +} + +// How many significant digits mycvt() should output. +// This cannot be more than 15, as this is the most that can be accurately represented +// in 64 bit double. Otherwise this code may crash. +#define DIGITS 15 + +static const uint64_t pows[] = { + 1LL, 10LL, 100LL, 1000LL, 10000LL, + 100000LL, 1000000LL, 10000000LL, 100000000LL, 1000000000LL, + 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL, +}; + +// The basic idea is we convert d to a 64 bit integer with DIGITS +// digits, and then print it out, putting dot in the right place. + +void mycvt(NUMBER d, char *buf) { + if (d < 0) { + *buf++ = '-'; + d = -d; + } + + if (!d) { + *buf++ = '0'; + *buf++ = 0; + return; + } + + int pw = (int)log10(d); + int e = 1; + + // if outside 1e-6 -- 1e21 range, we use the e-notation + if (d < 1e-6 || d > 1e21) { + // normalize number to 1.XYZ, save e, and reset pw + if (pw < 0) + d *= p10(-pw); + else + d /= p10(pw); + e = pw; + pw = 0; + } + + int trailingZ = 0; + int dotAfter = pw + 1; // at which position the dot should be in the number + + uint64_t dd; + + // normalize number to be integer with exactly DIGITS digits + if (pw >= DIGITS) { + // if the number is larger than DIGITS, we need trailing zeroes + trailingZ = pw - DIGITS + 1; + dd = (uint64_t)(d / p10(trailingZ) + 0.5); + } else { + dd = (uint64_t)(d * p10(DIGITS - pw - 1) + 0.5); + } + + // if number is less than 1, we need 0.00...00 at the beginning + if (dotAfter < 1) { + *buf++ = '0'; + *buf++ = '.'; + int n = -dotAfter; + while (n--) + *buf++ = '0'; + } + + // now print out the actual number + for (int i = DIGITS - 1; i >= 0; i--) { + uint64_t q = pows[i]; + // this may be faster than fp-division and fmod(); or maybe not + // anyways, it works + int k = '0'; + while (dd >= q) { + dd -= q; + k++; + } + *buf++ = k; + // if we're after dot, and what's left is zeroes, stop + if (dd == 0 && (DIGITS - i) >= dotAfter) + break; + // print the dot, if we arrived at it + if ((DIGITS - i) == dotAfter) + *buf++ = '.'; + } + + // print out remaining trailing zeroes if any + while (trailingZ-- > 0) + *buf++ = '0'; + + // if we used e-notation, handle that + if (e != 1) { + *buf++ = 'e'; + if (e > 0) + *buf++ = '+'; + itoa(e, buf); + } else { + *buf = 0; + } +} + +#if 0 +//% +TValue floatAsInt(TValue x) { + return doubleToInt(toDouble(x)); +} + +//% shim=numops::floatAsInt +function floatAsInt(v: number): number { return 0 } + +function testInt(i: number) { + if (floatAsInt(i) != i) + control.panic(101) + if (floatAsInt(i + 0.5) != null) + control.panic(102) + if (floatAsInt(i + 0.00001) != null) + control.panic(103) +} + +function testFloat(i: number) { + if (floatAsInt(i) != null) + control.panic(104) +} + +function testFloatAsInt() { + for (let i = 0; i < 0xffff; ++i) { + testInt(i) + testInt(-i) + testInt(i * 10000) + testInt(i << 12) + testInt(i + 0x3fff0001) + testInt(-i - 0x3fff0002) + testFloat(i + 0x3fffffff + 1) + testFloat((i + 10000) * 1000000) + } +} +#endif + +String toString(TValue v) { + ValType t = valType(v); + + if (t == ValType::String) { + return (String)v; + } else if (t == ValType::Number) { + char buf[64]; + + if (isInt(v)) { + itoa(numValue(v), buf); + return mkStringCore(buf); + } + + if (v == TAG_NAN) + return (String)(void *)sNaN; + + auto x = toDouble(v); + +#ifdef PXT_BOX_DEBUG + if (x == (int)x) { + itoa((int)x, buf); + return mkStringCore(buf); + } +#endif + + if (isinf(x)) { + if (x < 0) + return (String)(void *)sMInf; + else + return (String)(void *)sInf; + } else if (isnan(x)) { + return (String)(void *)sNaN; + } + mycvt(x, buf); + + return mkStringCore(buf); + } else if (t == ValType::Function) { + return (String)(void *)sFunction; + } else { + if (v == TAG_UNDEFINED) + return (String)(void *)sUndefined; + else if (v == TAG_FALSE) + return (String)(void *)sFalse; + else if (v == TAG_NAN) + return (String)(void *)sNaN; + else if (v == TAG_TRUE) + return (String)(void *)sTrue; + else if (v == TAG_NULL) + return (String)(void *)sNull; + return (String)(void *)sObject; + } +} + +} // namespace numops + +namespace Math_ { +//% +TNumber pow(TNumber x, TNumber y) { +#ifdef PXT_POWI + // regular pow() from math.h is 4k of code + return fromDouble(__builtin_powi(toDouble(x), toInt(y))); +#else + return fromDouble(::pow(toDouble(x), toDouble(y))); +#endif +} + +NUMBER randomDouble() { + return getRandom(UINT_MAX) / ((NUMBER)UINT_MAX + 1) + + getRandom(0xffffff) / ((NUMBER)UINT_MAX * 0xffffff); +} + +//% +TNumber random() { + return fromDouble(randomDouble()); +} + +//% +TNumber randomRange(TNumber min, TNumber max) { + if (isInt(min) && isInt(max)) { + int mini = numValue(min); + int maxi = numValue(max); + if (mini > maxi) { + int temp = mini; + mini = maxi; + maxi = temp; + } + if (maxi == mini) + return fromInt(mini); + else + return fromInt(mini + getRandom(maxi - mini)); + } else { + auto mind = toDouble(min); + auto maxd = toDouble(max); + if (mind > maxd) { + auto temp = mind; + mind = maxd; + maxd = temp; + } + if (maxd == mind) + return fromDouble(mind); + else { + return fromDouble(mind + randomDouble() * (maxd - mind)); + } + } +} + +#define SINGLE(op) return fromDouble(::op(toDouble(x))); + +//% +TNumber log(TNumber x){SINGLE(log)} + +//% +TNumber log10(TNumber x){SINGLE(log10)} + +//% +TNumber floor(TNumber x){SINGLE(floor)} + +//% +TNumber ceil(TNumber x){SINGLE(ceil)} + +//% +TNumber trunc(TNumber x){SINGLE(trunc)} + +//% +TNumber round(TNumber x) { + // In C++, round(-1.5) == -2, while in JS, round(-1.5) == -1. Align to the JS convention for + // consistency between simulator and device. The following does rounding with ties (x.5) going + // towards positive infinity. + return fromDouble(::floor(toDouble(x) + 0.5)); +} + +//% +int imul(int x, int y) { + return x * y; +} + +//% +int idiv(int x, int y) { + return x / y; +} +} // namespace Math_ + +namespace Array_ { +RefCollection *mk() { + auto r = NEW_GC(RefCollection); + MEMDBG("mkColl: => %p", r); + return r; +} +int length(RefCollection *c) { + return c->length(); +} +void setLength(RefCollection *c, int newLength) { + c->setLength(newLength); +} +void push(RefCollection *c, TValue x) { + c->head.push(x); +} +TValue pop(RefCollection *c) { + return c->head.pop(); +} +TValue getAt(RefCollection *c, int x) { + return c->head.get(x); +} +void setAt(RefCollection *c, int x, TValue y) { + c->head.set(x, y); +} +TValue removeAt(RefCollection *c, int x) { + return c->head.remove(x); +} +void insertAt(RefCollection *c, int x, TValue value) { + c->head.insert(x, value); +} +int indexOf(RefCollection *c, TValue x, int start) { + auto data = c->head.getData(); + auto len = c->head.getLength(); + for (unsigned i = 0; i < len; i++) { + if (pxt::eq_bool(data[i], x)) { + return (int)i; + } + } + return -1; +} +bool removeElement(RefCollection *c, TValue x) { + int idx = indexOf(c, x, 0); + if (idx >= 0) { + decr(removeAt(c, idx)); + return 1; + } + return 0; +} +} // namespace Array_ + +namespace pxt { +int debugFlags; + +//% +void *ptrOfLiteral(int offset); + +#ifdef PXT_VM +unsigned programSize() { + return 0; +} +#else +//% +unsigned programSize() { + return bytecode[17] * 8; +} +#endif + +void deepSleep() __attribute__((weak)); +//% +void deepSleep() {} + +int *getBootloaderConfigData() __attribute__((weak)); +int *getBootloaderConfigData() { + return NULL; +} + +//% +int getConfig(int key, int defl) { +#ifdef PXT_VM + int *cfgData = vmImg->configData; +#else + int *cfgData = bytecode ? *(int **)&bytecode[18] : NULL; +#endif + + if (cfgData) { + for (int i = 0;; i += 2) { + if (cfgData[i] == key) + return cfgData[i + 1]; + if (cfgData[i] == 0) + break; + } + } + + cfgData = getBootloaderConfigData(); + + if (cfgData) { + for (int i = 0;; i += 2) { + if (cfgData[i] == key) + return cfgData[i + 1]; + if (cfgData[i] == 0) + break; + } + } + + return defl; +} + +} // namespace pxt + +namespace pxtrt { +//% +TValue ldlocRef(RefRefLocal *r) { + return r->v; +} + +//% +void stlocRef(RefRefLocal *r, TValue v) { + r->v = v; +} + +//% +RefRefLocal *mklocRef() { + auto r = NEW_GC(RefRefLocal); + MEMDBG("mklocRef: => %p", r); + return r; +} + +// Store a captured local in a closure. It returns the action, so it can be chained. +//% +RefAction *stclo(RefAction *a, int idx, TValue v) { + // DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v); + a->stCore(idx, v); + return a; +} + +//% +void panic(int code) { + soft_panic(code); +} + +//% +String emptyToNull(String s) { + if (!s || IS_EMPTY(s)) + return NULL; + return s; +} + +//% +int ptrToBool(TValue p) { + if (p) { + decr(p); + return 1; + } else { + return 0; + } +} + +RefMap *mkMap() { + auto r = NEW_GC(RefMap); + MEMDBG("mkMap: => %p", r); + return r; +} + +TValue mapGetByString(RefMap *map, String key) { + int i = map->findIdx(key); + if (i < 0) { + return 0; + } + return map->values.get(i); +} + +#ifdef PXT_VM +#define IFACE_MEMBER_NAMES vmImg->ifaceMemberNames +#else +#define IFACE_MEMBER_NAMES *(uintptr_t **)&bytecode[22] +#endif + +int lookupMapKey(String key) { + auto arr = IFACE_MEMBER_NAMES; + auto len = *arr++; + int l = 1U; // skip index 0 - it's invalid + int r = (int)len - 1; + auto ikey = (uintptr_t)key; + if (arr[l] <= ikey && ikey <= arr[r]) { + while (l <= r) { + auto m = (l + r) >> 1; + if (arr[m] == ikey) + return m; + else if (arr[m] < ikey) + l = m + 1; + else + r = m - 1; + } + } else { + while (l <= r) { + int m = (l + r) >> 1; + auto cmp = String_::compare((String)arr[m], key); + if (cmp == 0) + return m; + else if (cmp < 0) + l = m + 1; + else + r = m - 1; + } + } + return 0; +} + +TValue mapGet(RefMap *map, unsigned key) { + auto arr = (String *)IFACE_MEMBER_NAMES; + auto r = mapGetByString(map, arr[key + 1]); + map->unref(); + return r; +} + +void mapSetByString(RefMap *map, String key, TValue val) { + int i = map->findIdx(key); + if (i < 0) { + map->keys.push((TValue)key); + map->values.push(val); + } else { + map->values.set(i, val); + } +} + +void mapSet(RefMap *map, unsigned key, TValue val) { + auto arr = (String *)IFACE_MEMBER_NAMES; + mapSetByString(map, arr[key + 1], val); + decr(val); + map->unref(); +} + +// +// Debugger +// + +// This is only to be called once at the beginning of lambda function +//% +void *getGlobalsPtr() { +#ifdef DEVICE_GROUP_ID_USER + fiber_set_group(DEVICE_GROUP_ID_USER); +#endif + + return globals; +} + +//% +void runtimeWarning(String s) { + // noop for now +} +} // namespace pxtrt +#endif + +namespace pxt { + +//% +ValType valType(TValue v) { + if (isTagged(v)) { + if (!v) + return ValType::Undefined; + + if (isInt(v) || v == TAG_NAN) + return ValType::Number; + if (v == TAG_TRUE || v == TAG_FALSE) + return ValType::Boolean; + else if (v == TAG_NULL) + return ValType::Object; + else { + oops(1); + return ValType::Object; + } +#ifdef PXT64 + } else if (isDouble(v)) { + return ValType::Number; +#endif + } else { + auto vt = getVTable((RefObject *)v); + if (vt->magic == VTABLE_MAGIC) + return vt->objectType; + else + return ValType::Object; + } +} + +PXT_DEF_STRING(sObjectTp, "object") +PXT_DEF_STRING(sBooleanTp, "boolean") +PXT_DEF_STRING(sStringTp, "string") +PXT_DEF_STRING(sNumberTp, "number") +PXT_DEF_STRING(sFunctionTp, "function") +PXT_DEF_STRING(sUndefinedTp, "undefined") + +//% expose +String typeOf(TValue v) { + switch (valType(v)) { + case ValType::Undefined: + return (String)sUndefinedTp; + case ValType::Boolean: + return (String)sBooleanTp; + case ValType::Number: + return (String)sNumberTp; + case ValType::String: + return (String)sStringTp; + case ValType::Object: + return (String)sObjectTp; + case ValType::Function: + return (String)sFunctionTp; + default: + oops(2); + return 0; + } +} + +// Maybe in future we will want separate print methods; for now ignore +void anyPrint(TValue v) { + if (valType(v) == ValType::Object) { + if (isRefCounted(v)) { + auto o = (RefObject *)v; + auto vt = getVTable(o); + auto meth = ((RefObjectMethod)vt->methods[1]); + if ((void *)meth == (void *)&anyPrint) + DMESG("[RefObject vt=%p cl=%d sz=%d]", o->vtable, vt->classNo, vt->numbytes); + else + meth(o); + } else { + DMESG("[Native %p]", v); + } + } else { +#ifndef X86_64 + String s = numops::toString(v); + DMESG("[%s %p = %s]", pxt::typeOf(v)->getUTF8Data(), v, s->getUTF8Data()); + decr((TValue)s); +#endif + } +} + +static void dtorDoNothing() {} + +#define PRIM_VTABLE(name, objectTp, tp, szexpr) \ + static uint32_t name##_size(tp *p) { return TOWORDS(sizeof(tp) + szexpr); } \ + DEF_VTABLE(name##_vt, tp, objectTp, (void *)&dtorDoNothing, (void *)&anyPrint, 0, \ + (void *)&name##_size) + +#define NOOP ((void)0) + +#define STRING_VT(name, fix, scan, gcsize, data, utfsize, length, dataAt) \ + static uint32_t name##_gcsize(BoxedString *p) { return TOWORDS(sizeof(void *) + (gcsize)); } \ + static void name##_gcscan(BoxedString *p) { scan; } \ + static const char *name##_data(BoxedString *p) { \ + fix; \ + return data; \ + } \ + static uint32_t name##_utfsize(BoxedString *p) { \ + fix; \ + return utfsize; \ + } \ + static uint32_t name##_length(BoxedString *p) { \ + fix; \ + return length; \ + } \ + static const char *name##_dataAt(BoxedString *p, uint32_t idx) { \ + fix; \ + return dataAt; \ + } \ + DEF_VTABLE(name##_vt, BoxedString, ValType::String, (void *)&dtorDoNothing, (void *)&anyPrint, \ + (void *)&name##_gcscan, (void *)&name##_gcsize, (void *)&name##_data, \ + (void *)&name##_utfsize, (void *)&name##_length, (void *)&name##_dataAt) + +void gcMarkArray(void *data); +void gcScan(TValue v); + +#if PXT_UTF8 +static const char *skipLookup(BoxedString *p, uint32_t idx, int packed) { + if (idx > p->skip.length) + return NULL; + auto ent = idx / PXT_STRING_SKIP_INCR; + auto data = packed ? PXT_SKIP_DATA_PACK(p) : PXT_SKIP_DATA_IND(p); + auto size = p->skip.size; + if (ent) { + auto off = packed ? p->skip_pack.list[ent - 1] : p->skip.list[ent - 1]; + data += off; + size -= off; + idx &= PXT_STRING_SKIP_INCR - 1; + } + return utf8Skip(data, size, idx); +} + +extern LLSegment workQueue; + +static uint32_t fixSize(BoxedString *p, uint32_t *len) { + uint32_t tlen = 0; + uint32_t sz = 0; + if (workQueue.getLength()) + oops(81); + workQueue.push((TValue)p); + while (workQueue.getLength()) { + p = (BoxedString *)workQueue.pop(); + if (IS_CONS(p)) { + workQueue.push((TValue)p->cons.right); + workQueue.push((TValue)p->cons.left); + } else { + tlen += p->getLength(); + sz += p->getUTF8Size(); + } + } + *len = tlen; + return sz; +} + +static void fixCopy(BoxedString *p, char *dst) { + if (workQueue.getLength()) + oops(81); + + workQueue.push((TValue)p); + while (workQueue.getLength()) { + p = (BoxedString *)workQueue.pop(); + if (IS_CONS(p)) { + workQueue.push((TValue)p->cons.right); + workQueue.push((TValue)p->cons.left); + } else { + auto sz = p->getUTF8Size(); + memcpy(dst, p->getUTF8Data(), sz); + dst += sz; + } + } +} + +// switches CONS representation into skip list representation +// does not switch representation of CONS' children +static void fixCons(BoxedString *r) { + uint32_t length = 0; + auto sz = fixSize(r, &length); + auto numSkips = length / PXT_STRING_SKIP_INCR; + // allocate first, while [r] still holds references to its children + // because allocation might trigger GC + auto data = (uint16_t *)gcAllocateArray(numSkips * 2 + sz + 1); + // copy, while [r] is still cons + fixCopy(r, (char *)(data + numSkips)); + // now, set [r] up properly + r->vtable = &string_skiplist16_vt; + r->skip.size = sz; + r->skip.length = length; + r->skip.list = data; + setupSkipList(r, NULL, 0); +} +#endif + +STRING_VT(string_inline_ascii, NOOP, NOOP, 2 + p->ascii.length + 1, p->ascii.data, p->ascii.length, + p->ascii.length, idx <= p->ascii.length ? p->ascii.data + idx : NULL) +#if PXT_UTF8 +STRING_VT(string_inline_utf8, NOOP, NOOP, 2 + p->utf8.size + 1, p->utf8.data, p->utf8.size, + utf8Len(p->utf8.data, p->utf8.size), utf8Skip(p->utf8.data, p->utf8.size, idx)) +STRING_VT(string_skiplist16, NOOP, if (p->skip.list) gcMarkArray(p->skip.list), 2 * sizeof(void *), + PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length, skipLookup(p, idx, 0)) +STRING_VT(string_skiplist16_packed, NOOP, NOOP, 2 + 2 + PXT_NUM_SKIP_ENTRIES(p) * 2 + p->skip.size + 1, + PXT_SKIP_DATA_PACK(p), p->skip.size, p->skip.length, skipLookup(p, idx, 1)) +STRING_VT(string_cons, fixCons(p), (gcScan((TValue)p->cons.left), gcScan((TValue)p->cons.right)), + 2 * sizeof(void *), PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length, + skipLookup(p, idx, 0)) +#endif + +PRIM_VTABLE(number, ValType::Number, BoxedNumber, 0) +PRIM_VTABLE(buffer, ValType::Object, BoxedBuffer, p->length) +// PRIM_VTABLE(action, ValType::Function, RefAction, ) + +void failedCast(TValue v, void *addr) { + DMESG("failed type check for %p @%p", v, addr); + auto vt = getAnyVTable(v); + if (vt) { + DMESG("VT %p - objtype %d classNo %d", vt, vt->objectType, vt->classNo); + } + + int code; + if (v == TAG_NULL) + code = PANIC_CAST_FROM_NULL; + else + code = PANIC_CAST_FIRST + (int)valType(v); + soft_panic(code); +} + +void missingProperty(TValue v) { + DMESG("missing property on %p", v); + soft_panic(PANIC_MISSING_PROPERTY); +} + +#ifdef PXT_PROFILE +struct PerfCounter *perfCounters; + +struct PerfCounterInfo { + uint32_t numPerfCounters; + char *perfCounterNames[0]; +}; + +#define PERF_INFO ((PerfCounterInfo *)(((uintptr_t *)bytecode)[13])) + +void initPerfCounters() { + auto n = PERF_INFO->numPerfCounters; + perfCounters = new PerfCounter[n]; + memset(perfCounters, 0, n * sizeof(PerfCounter)); +} + +void dumpPerfCounters() { + auto info = PERF_INFO; + DMESG("calls,us,name"); + for (uint32_t i = 0; i < info->numPerfCounters; ++i) { + auto c = &perfCounters[i]; + DMESG("%d,%d,%s", c->numstops, c->value, info->perfCounterNames[i]); + } +} + +void startPerfCounter(PerfCounters n) { + if (!perfCounters) + return; + auto c = &perfCounters[(uint32_t)n]; + if (c->start) + oops(50); + c->start = PERF_NOW(); +} + +void stopPerfCounter(PerfCounters n) { + if (!perfCounters) + return; + auto c = &perfCounters[(uint32_t)n]; + if (!c->start) + oops(51); + c->value += PERF_NOW() - c->start; + c->start = 0; + c->numstops++; +} +#endif + +// Exceptions + +#ifndef PXT_EXN_CTX +#define PXT_EXN_CTX() getThreadContext() +#endif + +typedef void (*RestoreStateType)(TryFrame *, ThreadContext *); +#ifndef pxt_restore_exception_state +#define pxt_restore_exception_state ((RestoreStateType)(((uintptr_t *)bytecode)[14])) +#endif + +//% +TryFrame *beginTry() { + auto ctx = PXT_EXN_CTX(); + auto frame = (TryFrame *)app_alloc(sizeof(TryFrame)); + frame->parent = ctx->tryFrame; + ctx->tryFrame = frame; + return frame; +} + +//% expose +void endTry() { + auto ctx = PXT_EXN_CTX(); + auto f = ctx->tryFrame; + if (!f) + oops(51); + ctx->tryFrame = f->parent; + app_free(f); +} + +//% expose +void throwValue(TValue v) { + auto ctx = PXT_EXN_CTX(); + auto f = ctx->tryFrame; + if (!f) { + DMESG("unhandled exception, value:"); + anyPrint(v); + target_panic(PANIC_UNHANDLED_EXCEPTION); + } + ctx->tryFrame = f->parent; + TryFrame copy = *f; + app_free(f); + ctx->thrownValue = v; + pxt_restore_exception_state(©, ctx); +} + +//% expose +TValue getThrownValue() { + auto ctx = PXT_EXN_CTX(); + auto v = ctx->thrownValue; + ctx->thrownValue = TAG_NON_VALUE; + if (v == TAG_NON_VALUE) + oops(51); + return v; +} + +//% expose +void endFinally() { + auto ctx = PXT_EXN_CTX(); + if (ctx->thrownValue == TAG_NON_VALUE) + return; + throwValue(getThrownValue()); +} + +// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function +uint32_t hash_fnv1(const void *data, unsigned len) { + const uint8_t *d = (const uint8_t *)data; + uint32_t h = 0x811c9dc5; + while (len--) + h = (h * 0x1000193) ^ *d++; + return h; +} + +// redefined in melody.cpp +__attribute__((weak)) int redirectSamples(int16_t *dst, int numsamples, int samplerate) { + return 0; +} + +} // namespace pxt diff --git a/libs/base/docs/blocks/pause-until.md b/libs/base/docs/blocks/pause-until.md new file mode 100644 index 00000000..24172331 --- /dev/null +++ b/libs/base/docs/blocks/pause-until.md @@ -0,0 +1,53 @@ +# pause Until + +Pause the current part of the program until a condition becomes true. + +```sig +pauseUntil(() => true) +``` + +Sometimes you need to wait in one part of a program for something to happen somewhere else in the program. This is done by pausing until some condition elsewhere becomes ``true``. Such a condition could be a value you set in an event block or a function that returns a [boolean](/types/boolean) . + +## Parameters + +* **condition**: a [boolean](/types/boolean) condition that restarts the program when it becomes ``true``. +* **timeOut**: an optional paramenter which is a [number](/types/number) of milliseconds to wait for the **condition** to become ``true``. The pause ends when the timeout has elapsed even if **condition** is still ``false``. + +## ~hint + +The code you have in **events** or inside **runInParallel** blocks will continue to execute while the current part of your program is paused. + +## ~ + +## Examples #example + +### Timer in a parallel block #ex1 + +Make a `5` second timer by counting time in a parallel code section. + +```blocks +let msecs = 0 +control.runInParallel(function () { + while (true) { + control.waitMicros(1000) + msecs += 1 + } +}) +pauseUntil(() => msecs > 5000) +``` + +### Timer in a boolean function #ex2 + +Wait on a five second timer function. + +```typescript +function waitFiveSeconds() : boolean { + for (let i = 0; i < 5000; i++) { + control.waitMicros(1000) + } + return true +} +pauseUntil(() => waitFiveSeconds()) +``` + +## #seealso \ No newline at end of file diff --git a/libs/base/docs/device/error-codes.md b/libs/base/docs/device/error-codes.md new file mode 100644 index 00000000..335eb0a1 --- /dev/null +++ b/libs/base/docs/device/error-codes.md @@ -0,0 +1,53 @@ +# Error codes + +## #error-info + +Your @boardname@ may encounter a situation that prevents it from running your code. The system software that runs the programs on your board may notify you that an error occurred. It might show this error as a numeric code on the display, LEDs, or as output on a data port. These are called _panic_ codes. When an error happens that causes a panic code, your program will stop and you'll need to reset the board to start again. + +## Panic codes + +Some panic codes are for general errors that might occur while your program runs. Other times, a device or resource you want to use isn't present or isn't working and you receive a panic code for that. Several panic codes are related to the use of memory and accessing data in it. + +* **20** (`PANIC_CODAL_OOM`): there is no free memory on the @boardname@ +* **21** (`PANIC_GC_OOM`): Garbage Collection can't allocate any more memory +* **22** (`PANIC_GC_TOO_BIG_ALLOCATION`): Garbage Collection can't allocate memory for the requested size +* **30** (`PANIC_CODAL_HEAP_ERROR`): a general memory allocation error +* **40** (`PANIC_CODAL_NULL_DEREFERENCE`): a memory pointer is NULL and points to an invalid location +* **50** (`PANIC_CODAL_USB_ERROR`): USB is not available or can't initialize, transmit, or receive +* **90** (`PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR`): actual board hardware doesn't match the configuration description +* **901** (`PANIC_INVALID_BINARY_HEADER`): the type header for the object is not valid +* **902** (`PANIC_OUT_OF_BOUNDS`): the object data portion is greater than the length defined for it +* **903** (`PANIC_REF_DELETED`): an object reference was deleted and the object is no longer valid +* **904** (`PANIC_SIZE`): the object size doesn't match the size defined for the type +* **905** (`PANIC_INVALID_VTABLE`): an object vtable is invalid or not initialized +* **906** (`PANIC_INTERNAL_ERROR`): an internal resource error +* **907** (`PANIC_NO_SUCH_CONFIG`): the specified device resource is not present +* **908** (`NO_SUCH_PIN`): the specified pin is not present on the board +* **909** (`PANIC_INVALID_ARGUMENT`): the argument value is out of range or the type or format is invalid +* **910** (`PANIC_MEMORY_LIMIT_EXCEEDED`): insufficient memory is available to satisfy and allocation request +* **911** (`PANIC_SCREEN_ERROR`): the screen isn't present or it can't properly display the output +* **912** (`PANIC_MISSING_PROPERTY`): the property requested is not present in the current object +* **913** (`PANIC_INVALID_IMAGE`): the data for a screen image data is invalid or formatted incorrectly +* **914** (`PANIC_CALLED_FROM_ISR`): the current code isn't allowed to run in an interrupt service routine (ISR) +* **915** (`PANIC_HEAP_DUMPED`): the contents of memory was output to a debug port +* **916** (`PANIC_STACK_OVERFLOW`): stack size limit for the fiber was exceeded +* **917** (`PANIC_BLOCKING_TO_STRING`): inline execution blocked due to an existing resume context +* **918** (`PANIC_VM_ERROR`): VM execution context error +* **920** (`PANIC_SETTINGS_CLEARED`): storage required for system settings, user settings were cleared +* **921** (`PANIC_SETTINGS_OVERLOAD`): frequency of writes to settings storage is too high +* **922** (`PANIC_SETTINGS_SECRET_MISSING`): settings storage in flash memory is inconsistent +* **923** (`PANIC_DELETE_ON_CLASS`): a settings key delete was attempted on a class +* **924** (`PANIC_OUT_OF_TIMERS`): no more timers are available +* **980** (`PANIC_CAST_FROM_UNDEFINED`): attempted cast from an `undefined` value to another type +* **981** (`PANIC_CAST_FROM_BOOLEAN`): attempted cast from a [boolean](/types/boolean) value to an incompatible type +* **982** (`PANIC_CAST_FROM_NUMBER`): attempted cast from a [number](/types) value to an incompatible type or no conversion is available +* **983** (`PANIC_CAST_FROM_STRING`): attempted cast from a [string](/types/string) value to an incompatible type or no conversion is available +* **984** (`PANIC_CAST_FROM_OBJECT`): attempted cast from an object to an incompatible type +* **985** (`PANIC_CAST_FROM_FUNCTION`): attempted cast from a function to a non-function type +* **989** (`PANIC_CAST_FROM_NULL`): attempted cast from a `null` value to another type + +## #specific + +## See also + +[panic](/reference/control/panic), [assert](/reference/control/assert) diff --git a/libs/base/docs/reference/console.md b/libs/base/docs/reference/console.md new file mode 100644 index 00000000..0bf10cc2 --- /dev/null +++ b/libs/base/docs/reference/console.md @@ -0,0 +1,13 @@ +# Console + +Output text and data values to the console. + +```cards +console.log(""); +console.logValue("x", 0); +``` + +## See also + +[log](/reference/console/log), +[log value](/reference/console/log-value) \ No newline at end of file diff --git a/libs/base/docs/reference/console/log-value.md b/libs/base/docs/reference/console/log-value.md new file mode 100644 index 00000000..48553717 --- /dev/null +++ b/libs/base/docs/reference/console/log-value.md @@ -0,0 +1,38 @@ +# log value + +Write a **name:value** pair as a line of text to the console output. + +```sig +console.logValue("x", 0); +``` + +A **name:value** pair is a string that has both a name for a value and the value +itself. If you want to send a temperature value of 32 degrees as a _name:value_ pair, +it would go to the console output as this: "temperature:32". This is a good way to +connect a number value to its meaning. + +So, ``||console:log value||`` does this but you give the name and the value as two parts and it +sends it as a pair. + +## Parameters + +* **name**: a [string](/types/string) that is the name part of the _name:value_ pair +* **value**: a [number](/types/number) that is the value part of the _name:value_ pair + +## Example #example + +Send _name:value_ pairs for odd and even numbers to the console output. + +```blocks +for (let i = 0; i < 10; i++) { + if (i % 2 > 0) { + console.logValue("odd", i) + } else { + console.logValue("even", i) + } +} +``` + +## See also #seealso + +[log](/reference/console/log) \ No newline at end of file diff --git a/libs/base/docs/reference/console/log.md b/libs/base/docs/reference/console/log.md new file mode 100644 index 00000000..ec910439 --- /dev/null +++ b/libs/base/docs/reference/console/log.md @@ -0,0 +1,33 @@ +# log + +Write a line of text to the console output. + +```sig +console.log(""); +``` + +A line of text is a string that has two special characters added at the end: _carriage return_ +and _line feed_. These characters are really just codes that mean start a new line. +Sometimes they appear in code as ``"\r\n"``. + +After using ``||console:log||``, any new text written to the console output will begin on a new line. + +With ``||console:log||``, the new line characters are automatically added for you. You only need to give the text you want to write. + +## Parameters + +* **text**: the [string](/types/string) to write to the console output. + +## Example #example + +Write two greeting messages to the console output. + +```blocks +console.log("How are you today?"); +pause(5000); +console.log("Well that's great! I'm doing well too."); +``` + +## See also #seealso + +[log value](/reference/console/log-value) \ No newline at end of file diff --git a/libs/base/docs/reference/control.md b/libs/base/docs/reference/control.md new file mode 100644 index 00000000..cca81f9a --- /dev/null +++ b/libs/base/docs/reference/control.md @@ -0,0 +1,25 @@ +# Control + +Program controls and events. + +```cards +control.millis(); +control.runInParallel(() => { + +}); +control.reset(); +control.waitMicros(4); +control.deviceSerialNumber(); +``` + +## Advanced #advanced + +```cards +control.raiseEvent(0, 0); +control.onEvent(0, 0, () => { + +}); +control.assert(false, 0); +control.deviceDalVersion(); +control.panic(0); +``` diff --git a/libs/base/docs/reference/control/assert.md b/libs/base/docs/reference/control/assert.md new file mode 100644 index 00000000..8c3c16ff --- /dev/null +++ b/libs/base/docs/reference/control/assert.md @@ -0,0 +1,33 @@ +# assert + +Display an error number and stop the program if the assertion condition is false. + +```sig +control.assert(false, 0) +``` + +You can insist that your program will stop at an assert block if a certain condition you check is false. The error number in the assert is written to the serial port with a failure message. + +## Parameters + +* **cond**: a [boolean](/types/boolean) where true means everything is ok or false which means, stop the program! +* **code**: an error [number](/types/number) you match to an error situation in your program. + +## Example #example + +Stop the program if a sensor connected to pin `A0` sends a low (`0`) signal. + +```blocks +forever(function () { + control.assert((pins.A0.digitalRead() == 1), 15) + pause(1000) +}) +``` + +## See also #seealso + +[panic](/reference/control/panic) + +```package +base +``` \ No newline at end of file diff --git a/libs/base/docs/reference/control/device-dal-version.md b/libs/base/docs/reference/control/device-dal-version.md new file mode 100644 index 00000000..adec6fc5 --- /dev/null +++ b/libs/base/docs/reference/control/device-dal-version.md @@ -0,0 +1,25 @@ +# device Dal Version + +Get the version information for the system software on the @boardname@. + +```sig +control.deviceDalVersion() +``` + +## Returns + +* a [string](/types/string) that represents the version of the system software (DAL) on the board. + +Returns `"sim"` when running the simulator, and `"linux"` when running on Raspberry Pi. + +## Example #example + +Write the system software version to the serial port. + +```blocks +serial.writeLine("DAL version = " + control.deviceDalVersion()); +``` + +## See also #seealso + +[device serial number](/reference/control/device-serial-number) diff --git a/libs/base/docs/reference/control/device-serial-number.md b/libs/base/docs/reference/control/device-serial-number.md new file mode 100644 index 00000000..871ad9ba --- /dev/null +++ b/libs/base/docs/reference/control/device-serial-number.md @@ -0,0 +1,25 @@ +# device Serial Number + +Get the serial number for the @boardname@ + +```sig +control.deviceSerialNumber() +``` + +The system software in your board creates a unique number to identify the board. You can use this number in your program if you want to know which board is running your program. + +## Returns + +* a [number](/types/number) that is created to uniquely identify this board. + +## Example #example + +Write the board serial number to the serial port. + +```blocks +serial.writeValue("serialnumber", control.deviceSerialNumber()); +``` + +## See also #seealso + +[device dal version](/reference/control/device-dal-version) \ No newline at end of file diff --git a/libs/base/docs/reference/control/millis.md b/libs/base/docs/reference/control/millis.md new file mode 100644 index 00000000..ed531c13 --- /dev/null +++ b/libs/base/docs/reference/control/millis.md @@ -0,0 +1,25 @@ +# millis + +Get the number of milliseconds of time passed since the board was turned on. + +```sig +control.millis() +``` + +## Returns + +* the [number](/types/number) of milliseconds of time since the board was turned on. + +## Example #example + +Find how many days, hours, minutes, and seconds the @boardname@ has been running. + +```blocks +let msecs = control.millis() +let seconds = msecs / 1000 +let mins = seconds / 60 +let hours = mins / 60 +let days = hours / 24 +``` + +## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/on-event.md b/libs/base/docs/reference/control/on-event.md new file mode 100644 index 00000000..07499cf1 --- /dev/null +++ b/libs/base/docs/reference/control/on-event.md @@ -0,0 +1,93 @@ +# on Event + +Run some code when a registered event happens. + +```sig +control.onEvent(0, 0, () => {}) +``` +Instead of waiting inside of a loop that is part the main program, an event block is +a good way to have some extra code respond to something that happens with the board or +in your program. + +It works like this: some code in another part of the program decides it wants to announce +that something special or important just happened. It does this by _raising_ an _event_. +Some other code is placed inside an ``||control:on event||`` block. The ``||control:on event||`` block _registers_ +itself to run when a matching event is _raised_. + +Your program decides what an event should be and makes it official by _registering_ the event along with +a source identification number (id), **src**. The id in **src** is a way to know what **_thing_** is causing an event, +like a sensor, or some special time period that is now over. The **value** tells what the cause of the +event is. + +### Why use events? + +If you want to run some code when a status changes, you might do it this way +in the main part of the program: + +```blocks +let nowStatus = false +control.runInParallel(() => { + control.waitMicros(10000) + nowStatus = true +}) + +let lastStatus = nowStatus; +while(lastStatus == nowStatus) { + control.waitMicros(1000) +} +``` +The [``||loops:while||``](/blocks/loops/while) loop checks for a change in `nowStatus`. The problem is that your program is stuck +in the loop until `nowStatus` changes and it can't do any more work until then. + +But, we can change the program to use an event instead of waiting in a loop. Let's register an event +and give it a source identifier, or **src**, of `15` and a cause **value** of `1`: + +```blocks +let because = 0; +control.runInParallel(() => { + control.waitMicros(100000) + control.raiseEvent(15, 1) +}) + +control.onEvent(15, 1, () => { + because = 1; +}) +``` + +So, you see that the program registered an event known as `15`, `1`. The source is known by `15` and the +cause of the event is `1`. Why use these numbers? Well, let's say that you have a moisture sensor connected +to your board. You could make it known to your program that any event that comes from a source of `15` is about your sensor. You can say that a cause of `1` means things are too dry. + +## Parameters + +* **src**: the identification [number](/types/number) (the source) of this event, such as: `10`. +* **value**: a [number](/types/number) that tells what the cause of the event is, like: `4`. +* **handler**: the code to run when the event happens. + +## Example #example + +Register two events coming from source `22`. Write to the console when +the events of `0` and `1` are _raised_. + +```blocks +const myNotify = 22 + +control.runInParallel(function() { + for (let i = 0; i < 2; i++) { + pause(1000) + control.raiseEvent(myNotify, i) + } +}) + +control.onEvent(myNotify, 0, () => { + console.logValue("myNotify", 0) +}) + +control.onEvent(myNotify, 1, () => { + console.logValue("myNotify", 1) +}) +``` + +## See also ##seealso + +[raise event](/reference/control/raise-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/panic.md b/libs/base/docs/reference/control/panic.md new file mode 100644 index 00000000..93479d3c --- /dev/null +++ b/libs/base/docs/reference/control/panic.md @@ -0,0 +1,37 @@ +# panic + +Display an error number and stop the program. + +```sig +control.panic(0) +``` + +If your board has some way to display error information, ``||panic||`` will work +with it to show error numbers. + +Your program stops when you use ``||panic||``. Use this when you think something bad enough has +happened and your program can't run properly anymore. + +## Parameters + +* **code**: an error [number](/types/number) you match to an error situation in your program. + +## Example #example + +Send a 'code red' error that you created to the error display if the input from pin `A0` is +lower than `10`. + +```blocks +let codeRed = 1 +let codeBlue = 2 + +if (pins.A0.analogRead() < 10) { + control.panic(codeRed) +} +``` + +## See also #seealso + +[assert](/reference/control/assert) + +[Error Codes](/device/error-codes) \ No newline at end of file diff --git a/libs/base/docs/reference/control/raise-event.md b/libs/base/docs/reference/control/raise-event.md new file mode 100644 index 00000000..4aa3cbc6 --- /dev/null +++ b/libs/base/docs/reference/control/raise-event.md @@ -0,0 +1,61 @@ +# raise Event + +Announce that something happened at an event source. + +```sig +control.raiseEvent(0, 0) +``` +You use ``||control:raise event||`` to announce that something happened with the board or something special +happened in your program. You do this if there are other parts of your program that might want +to know about it. + +If you've added some [``||control:on event||``](/reference/control/on-event) blocks to your program, +the code inside them will run if the **src** and **value** numbers are the same as those with +``||control:raise event||``. The **src** tells about where the event is coming from. You pick a number +for it to identify something like a sensor or a special situation in your program. If you want +to announce that it's getting dark, you can make **src** something like `51` for the light sensor's +source number. This means that anything you want to announce about the light sensor, you raise +event with `51`. + +Many events can happen to a single source (**src**). With the light sensor you can announce that +its getting darker or lighter. This is the cause of the event, the **value**. So, for the light +sensor (the source number `51`) you might add two events for **value**: `1` for darker and `2` for lighter. + +With the light sensor example, you tell the program that it's getting darker: + +```block +control.raiseEvent(51, 1) +``` + +## Parameters + +* **src**: the identification [number](/types/number) (the source) of this event, such as: `10`. +* **value**: a [number](/types/number) tells what the cause of the event is, like: `4`. + +## Example #example + +Register two events coming from source `22`. Write to the console when +the events of `0` and `1` are _raised_. + +```blocks +const myNotify = 22; + +control.runInParallel(function() { + for (let i = 0; i < 2; i++) { + pause(1000); + control.raiseEvent(myNotify, i); + } +}) + +control.onEvent(myNotify, 0, () => { + console.logValue("myNotify", 0) +}) + +control.onEvent(myNotify, 1, () => { + console.logValue("myNotify", 1) +}) +``` + +## See also #seealso + +[on event](/reference/control/on-event), [wait for event](/reference/control/wait-for-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/reset.md b/libs/base/docs/reference/control/reset.md new file mode 100644 index 00000000..9c845fca --- /dev/null +++ b/libs/base/docs/reference/control/reset.md @@ -0,0 +1,20 @@ +# reset + +Reset the board and start the program from the beginning. + +```sig +control.reset() +``` + +Everything that the program did with the board is set back to the way it was before the +program started. The program starts over again from the beginning. + +## Example #example + +Reset the board and begin again. + +```blocks +control.reset() +``` + +## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/run-in-background.md b/libs/base/docs/reference/control/run-in-background.md new file mode 100644 index 00000000..169d410f --- /dev/null +++ b/libs/base/docs/reference/control/run-in-background.md @@ -0,0 +1,3 @@ +# run In Background + +This function is deprecated and replaced by [run in parallel](/reference/control/run-in-parallel). \ No newline at end of file diff --git a/libs/base/docs/reference/control/run-in-parallel.md b/libs/base/docs/reference/control/run-in-parallel.md new file mode 100644 index 00000000..80014099 --- /dev/null +++ b/libs/base/docs/reference/control/run-in-parallel.md @@ -0,0 +1,75 @@ +# run In Parallel + +Run some other code at the same time that your main program code runs. + +```sig +control.runInParallel(() => {}) +``` + +Sometimes you want your program to work on more than one thing at a time. The main part of your program is +always put in [``||on start||``](/blocks/on-start). But, you can also put some other part of your +program in ``||control:run in parallel||``. This is useful when you want your program to keep doing important things +and you don't want to wait for some other actions to happen first. + +## Separate tasks #tasks + +As an example, you could have a small task to rotate a bit in a 16 character +string of zeros. This is placed inside a ``||control:run in parallel||`` block: + +```blocks +let bitPos = 0 +let rorit = true +let zeros = "" + +control.runInParallel(function() { + while (rorit) { + if (bitPos > 15) { + bitPos = 0 + } + zeros = "" + for (let i = 0; i < 16; i++) { + if (bitPos == i) { + zeros = zeros + "1" + } else { + zeros = zeros + "0" + } + } + console.log(zeros) + pause(200) + } +}) +``` + +Code is added to the main part of the program to turn the bit rotation on, pause for `5` seconds and then turn it off. It pauses for another `5` seconds and then trys to turn the bit rotation back on. However, the parallel task has finished and +the bit rotation won't start again. + +```blocks +let rorit = true +pause(5000) +rorit = false +pause(5000) +rorit = true +``` + +## Parameters + +* **a**: the code to run in the background. + +## Example #example + +Use a parallel task to generate a magic number. In the main program check the value of the magic number twice. The first time check the value right away. The +second time, check `2` seconds later after the parallel task has time to run. + +```blocks +let magic = 0 + +control.runInParallel(function() { + magic = Math.randomRange(1000, 5000) +}) + +console.logValue("magic", magic) +pause(2000) +console.logValue("magic", magic) +``` + +## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/wait-for-event.md b/libs/base/docs/reference/control/wait-for-event.md new file mode 100644 index 00000000..c10a8fea --- /dev/null +++ b/libs/base/docs/reference/control/wait-for-event.md @@ -0,0 +1,63 @@ +# wait For Event + +Stop running the current code and wait for an event. + +```sig +control.waitForEvent(0, 0) +``` +You might want your code to stop for a while until some event you're expecting happens. +If you want your code to pause until a known event happens, use a ``||control:wait for event||`` block. +A known event is something you identify that happens on the board or in your program. +An event has both a source and a cause. The source is where the event comes from, like a sensor or +some condition in your program. The cause is what made the event happen at the source. + +You assign numbers for your event sources and causes. These numbers are used by [``||control:raise event||``](/reference/control/raise-event) to announce to your program that an event just happened. + +As an example, you could make a timer that always causes an event every 100 milliseconds. The source +number for the timer is `6` and the cause value is `1`. The program could wait for one of the time +events like this: + +```blocks +const myTimer = 6; +const timerTimeout = 1; + +control.runInParallel(function() { + while (true) { + control.waitMicros(100000) + control.raiseEvent(myTimer, timerTimeout) + } +}) + +control.waitForEvent(myTimer, timerTimeout) +``` + +## Parameters + +* **id**: the identification [number](/types/number) (the source) of this event, such as: `10`. +* **value**: a [number](/types/number) tells what the cause of the event is, like: `4`. + +## Example #example + +Make a timeout timer to signal every 2 seconds. Wait two times and write to the +console each time. + +```blocks +const myTimer = 6; +const timerTimeout = 1; + +control.runInParallel(function() { + while (true) { + pause(2000) + control.raiseEvent(myTimer, timerTimeout) + } +}) + +control.waitForEvent(myTimer, timerTimeout) +console.log("Timer timeout") +control.waitForEvent(myTimer, timerTimeout) +console.log("Timer timeout") +``` + +## See also #seealso + +[raise event](/reference/control/raise-event), [on event](/reference/control/on-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/wait-micros.md b/libs/base/docs/reference/control/wait-micros.md new file mode 100644 index 00000000..21b0b557 --- /dev/null +++ b/libs/base/docs/reference/control/wait-micros.md @@ -0,0 +1,26 @@ +# wait Micros + +Make the part of the program running right now wait for some number of microseconds. + +```sig +control.waitMicros(10) +``` +The code inside the current block, such as a ``||on start||``, ``||control:run in parallel||``, and +``||control:on event||`` , waits for some amount of time. The time number is in microseconds (one-millionth of a second). + +## Parameters + +* **micros**: the [number](/types/number) of microseconds for this block of code to wait for. + +## Example #example + +Turn on an a sensor that has a control signal connected to pin `D4`. Wait `20` microseconds +for the sensor to detect something, then read the sensor value on pin `A4`. + +```blocks +pins.D4.digitalWrite(true) +control.waitMicros(20) +let temperature = pins.A4.analogRead() +``` + +## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/input.md b/libs/base/docs/reference/input.md new file mode 100644 index 00000000..7d410da1 --- /dev/null +++ b/libs/base/docs/reference/input.md @@ -0,0 +1,53 @@ +# Input + +Events and data from sensors + +## Accelerometer #acceleration + +```cards +input.onGesture(Gesture.Shake, () => { + +}) +input.setAccelerometerRange(AcceleratorRange.OneG) +input.acceleration(Dimension.X) +input.rotation(Rotation.Pitch) + +``` + +## Light sensor #lightsensor + +```cards +input.onLightConditionChanged(LightCondition.Dark, () => { + +}) +input.lightLevel() +``` + +## Buttons #buttons + +```cards +input.buttonA.isPressed() +input.buttonA.wasPressed() +input.onSwitchMoved(SwitchDirection.Left, () => { + +}) +input.buttonA.onEvent(ButtonEvent.Click, () => { + +}) +``` + +## Microphone #microphone + +```cards +input.onLoudSound(() => {}) +input.soundLevel() +``` + +## Thermometer #thermometer + +```cards +input.onTemperatureConditionChanged(TemperatureCondition.Hot, 15, TemperatureUnit.Celsius, () => { + +}) +input.temperature(TemperatureUnit.Celsius) +``` diff --git a/libs/base/docs/reference/loops/forever.md b/libs/base/docs/reference/loops/forever.md new file mode 100644 index 00000000..2cb1f480 --- /dev/null +++ b/libs/base/docs/reference/loops/forever.md @@ -0,0 +1,33 @@ +# forever + +Run a part of the program in the background and keep running it over again. + +```sig +forever(() => { +}) +``` + +The code you have in a ``||loops:forever||`` loop will run and keep repeating itself the whole time your +program is active. Code in other parts of your program won't stop while your ``||loops:forever||`` +loop is running. This includes other ``||loops:forever||`` loops and the [``||control:run in parallel||``](/reference/control/run-in-parallel) block. + +## Parameters + +* **a**: the code to keep running over and over again. + +## Example #example + +Create an mood generator that writes a current mood to the console every `5` seconds. + +```blocks +let mood = ["happy", "sad", "joyful", "angry"] +forever(function () { + console.log("mood = " + mood[Math.randomRange(0, 3)]) + pause(5000) +}) +``` + +## See also #seealso + +[while](/blocks/loops/while), [repeat](/blocks/loops/repeat), +[run in parallel](/reference/control/run-in-parallel) diff --git a/libs/base/docs/reference/loops/pause.md b/libs/base/docs/reference/loops/pause.md new file mode 100644 index 00000000..0d902561 --- /dev/null +++ b/libs/base/docs/reference/loops/pause.md @@ -0,0 +1,31 @@ +# pause + +Pause a part of the program for some number of milliseconds. + +```sig +pause(400) +``` + +When code in a block comes to a ``||control:pause||``, it will wait the amount of time you tell it to. Code +in blocks like ``||loops:forever||`` and ``||control:run in parallel||`` will keep running while code in some other +block is waiting at a ``||control:pause||``. + +## Parameters + +* **ms**: the [number](/types/number) of milliseconds that you want to pause for. So, 100 milliseconds = 1/10 second, and 1000 milliseconds = 1 second. + +## Example #example + +Write the first five natural numbers to the console but wait one-half second between each write. + +```blocks +for (let i = 0; i < 5; i++) { + console.logValue("naturals", i + 1) + pause(500) +} +``` + +## See also #seealso + +[while](/blocks/loops/while), [for](/blocks/loops/for), +[forever](/reference/loops/forever) diff --git a/libs/base/docs/reference/text/convert-to-text.md b/libs/base/docs/reference/text/convert-to-text.md new file mode 100644 index 00000000..5cf823c2 --- /dev/null +++ b/libs/base/docs/reference/text/convert-to-text.md @@ -0,0 +1,34 @@ +# convert to text + +Change the value of any [type](/types) into a text [string](/types/string). + +```sig +convertToText(123) +``` + +## Parameters + +* **value**: a value of some [type](/types) to convert to a [string](/types/string). + +## Returns + +* a [string](/types/string) that is a text representation of **value**. + +## Example #example + +Convert a boolean and a number value into strings and join them in a sentence. + +```blocks +let myBoolean = false +let myNumber = 0 + +myBoolean = true +myNumber = 123 + +let myString = "It is " + convertToText(myBoolean) + " that " + convertToText(myNumber) + " is now a string!" +``` + +## Sea also #seealso + +[parse int](/reference/text/parse-int), +[parse float](/reference/text/parse-float) diff --git a/libs/base/enums.d.ts b/libs/base/enums.d.ts old mode 100755 new mode 100644 diff --git a/libs/base/eventcontext.ts b/libs/base/eventcontext.ts new file mode 100644 index 00000000..8c270f09 --- /dev/null +++ b/libs/base/eventcontext.ts @@ -0,0 +1,289 @@ +namespace control { + /** + * Run code when a registered event happens. + * @param id the event compoent id + * @param value the event value to match + */ + //% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src|with value %value" + //% blockExternalInputs=1 + //% help="control/on-event" + export function onEvent(src: number, value: number, handler: () => void, flags = 16) { // EVENT_LISTENER_DEFAULT_FLAGS + const ctx = control.eventContext(); + if (!ctx) + control.internalOnEvent(src, value, handler, flags); + else + ctx.registerHandler(src, value, handler, flags); + } + + export class FrameCallback { + order: number + handler: () => void + } + + class EventHandler { + constructor( + public src: number, + public value: number, + public handler: () => void, + public flags: number + ) { } + + register() { + control.internalOnEvent(this.src, this.value, () => { + if (this.handler) this.handler(); + }, this.flags) + } + + unregister() { + control.internalOnEvent(this.src, this.value, doNothing, this.flags); + } + } + + function doNothing() { } + + + + export class EventContext { + private handlers: EventHandler[]; + private frameCallbacks: FrameCallback[]; + private frameWorker: number; + private framesInSample: number; + private timeInSample: number; + public deltaTimeMillis: number; + private prevTimeMillis: number; + private idleCallbacks: (() => void)[]; + + static lastStats: string; + static onStats: (stats: string) => void; + + constructor() { + this.handlers = []; + this.framesInSample = 0; + this.timeInSample = 0; + this.deltaTimeMillis = 0; + this.frameWorker = 0; + this.idleCallbacks = undefined; + if (!EventContext.lastStats) { + EventContext.lastStats = ""; + } + } + + get deltaTime() { + return this.deltaTimeMillis / 1000; + } + + private runCallbacks() { + control.enablePerfCounter("all frame callbacks") + + let loopStart = control.millis() + this.deltaTimeMillis = loopStart - this.prevTimeMillis; + this.prevTimeMillis = loopStart; + for (let f of this.frameCallbacks) { + f.handler() + } + let runtime = control.millis() - loopStart + this.timeInSample += runtime + this.framesInSample++ + if (this.timeInSample > 1000 || this.framesInSample > 30) { + const fps = this.framesInSample / (this.timeInSample / 1000); + EventContext.lastStats = `fps:${Math.round(fps)}`; + if (fps < 99) + EventContext.lastStats += "." + (Math.round(fps * 10) % 10) + if (control.ramSize() > 2000000 && control.profilingEnabled()) { + control.dmesg(`${(fps * 100) | 0}/100 fps - ${this.framesInSample} frames`) + control.gc() + control.dmesgPerfCounters() + } + this.timeInSample = 0 + this.framesInSample = 0 + } + let delay = Math.max(1, 20 - runtime) + + return delay + } + + private runningCallbacks: boolean; + private registerFrameCallbacks() { + if (!this.frameCallbacks) return; + + const worker = this.frameWorker; + control.runInParallel(() => { + if (this.runningCallbacks) { + // this context is still running in a different fiber; + // delay until the other fiber doing so has ceased. + pauseUntil(() => !this.runningCallbacks); + } + this.runningCallbacks = true; + + this.framesInSample = 0; + this.timeInSample = 0; + this.deltaTimeMillis = 0; + this.prevTimeMillis = control.millis(); + + while (worker == this.frameWorker) { + let delay = this.runCallbacks() + pause(delay) + } + + this.runningCallbacks = false; + }) + } + + register() { + for (const h of this.handlers) + h.register(); + this.registerFrameCallbacks(); + } + + unregister() { + for (const h of this.handlers) + h.unregister(); + this.frameWorker++; + } + + registerFrameHandler(order: number, handler: () => void): FrameCallback { + if (!this.frameCallbacks) { + this.frameCallbacks = []; + this.registerFrameCallbacks(); + } + + const fn = new FrameCallback() + fn.order = order + fn.handler = handler + for (let i = 0; i < this.frameCallbacks.length; ++i) { + if (this.frameCallbacks[i].order > order) { + this.frameCallbacks.insertAt(i, fn) + return fn; + } + } + this.frameCallbacks.push(fn); + return fn; + } + + unregisterFrameHandler(fn: FrameCallback) { + if (!fn || !this.frameCallbacks) return; + const i = this.frameCallbacks.indexOf(fn); + if (i > -1) + this.frameCallbacks.splice(i, 1); + } + + registerHandler(src: number, value: number, handler: () => void, flags: number) { + // already there? + for (const h of this.handlers) { + if (h.src == src && h.value == value) { + h.flags = flags; + h.handler = handler; + return; + } + } + // register and push + const hn = new EventHandler(src, value, handler, flags); + this.handlers.push(hn); + hn.register(); + } + + addIdleHandler(handler: () => void) { + if (!this.idleCallbacks) { + this.idleCallbacks = []; + this.registerHandler(15/*DAL.DEVICE_ID_SCHEDULER*/, 2/*DAL.DEVICE_SCHEDULER_EVT_IDLE*/, () => this.runIdleHandler(), 16); + } + this.idleCallbacks.push(handler); + } + + removeIdleHandler(handler: () => void) { + if (handler && this.idleCallbacks) + this.idleCallbacks.removeElement(handler); + } + + private runIdleHandler() { + if (this.idleCallbacks) { + const ics = this.idleCallbacks.slice(0); + ics.forEach(ic => ic()); + } + } + } + let eventContexts: EventContext[]; + + /** + * Gets the current event context if any + */ + export function eventContext(): EventContext { + return eventContexts ? eventContexts[eventContexts.length - 1] : undefined; + } + + /** + * Pushes a new event context and clears all handlers + */ + export function pushEventContext(): EventContext { + if (!eventContexts) + eventContexts = []; + + // unregister previous context + const ctx = eventContext(); + if (ctx) ctx.unregister(); + // register again + const n = new EventContext(); + eventContexts.push(n); + return n; + } + + /** + * Pops the current event context and restore handlers if any previous context + */ + export function popEventContext() { + if (!eventContexts) return; + + // clear current context + const ctx = eventContexts.pop(); + if (!ctx) return; + ctx.unregister(); + + // register old context again + const context = eventContexts[eventContexts.length - 1]; + if (context) + context.register(); + else + eventContexts = undefined; + } + + let _idleCallbacks: (() => void)[]; + /** + * Registers a function to run when the device is idling + * @param handler + */ + export function onIdle(handler: () => void) { + if (!handler) return; + + const ctx = eventContext(); + if (ctx) ctx.addIdleHandler(handler); + else { + if (!_idleCallbacks) { + _idleCallbacks = []; + control.runInBackground(function () { + while (_idleCallbacks) { + _idleCallbacks.slice(0).forEach(cb => cb()); + pause(20); + } + }) + /* + control.internalOnEvent( + 15. // DAL.DEVICE_ID_SCHEDULER + 2, // DAL.DEVICE_SCHEDULER_EVT_IDLE + function() { + pins.LED.digitalWrite(on = !on); + if (_idleCallbacks) + _idleCallbacks.slice(0).forEach(cb => cb()); + }, 192); // MESSAGE_BUS_LISTENER_IMMEDIATE + */ + } + _idleCallbacks.push(handler); + } + } + + export function removeIdleHandler(handler: () => void) { + if (!handler) return; + const ctx = eventContext(); + if (ctx) ctx.removeIdleHandler(handler); + else if (_idleCallbacks) _idleCallbacks.removeElement(handler); + } +} \ No newline at end of file diff --git a/libs/base/fixed.ts b/libs/base/fixed.ts new file mode 100644 index 00000000..1c3f8409 --- /dev/null +++ b/libs/base/fixed.ts @@ -0,0 +1,75 @@ +interface Fx8 { + _dummyFx8: string; +} + +function Fx8(v: number) { + return ((v * 256) | 0) as any as Fx8 +} + +namespace Fx { + export const zeroFx8 = 0 as any as Fx8 + export const oneHalfFx8 = 128 as any as Fx8 + export const oneFx8 = 256 as any as Fx8 + export const twoFx8 = 512 as any as Fx8 + + export function neg(a: Fx8) { + return (-(a as any as number)) as any as Fx8 + } + export function toIntShifted(a: Fx8, n: number) { + return (a as any as number) >> (n + 8) + } + export function add(a: Fx8, b: Fx8) { + return ((a as any as number) + (b as any as number)) as any as Fx8 + } + export function iadd(a: number, b: Fx8) { + return ((a << 8) + (b as any as number)) as any as Fx8 + } + export function sub(a: Fx8, b: Fx8) { + return ((a as any as number) - (b as any as number)) as any as Fx8 + } + export function mul(a: Fx8, b: Fx8) { + return (Math.imul((a as any as number), (b as any as number)) >> 8) as any as Fx8 + } + export function imul(a: Fx8, b: number) { + return Math.imul((a as any as number), (b as any as number)) as any as Fx8 + } + export function div(a: Fx8, b: Fx8) { + return Math.idiv((a as any as number) << 8, b as any as number) as any as Fx8 + } + export function idiv(a: Fx8, b: number) { + return Math.idiv((a as any as number), b) as any as Fx8 + } + export function compare(a: Fx8, b: Fx8) { + return (a as any as number) - (b as any as number) + } + export function abs(a: Fx8) { + if ((a as any as number) < 0) + return (-(a as any as number)) as any as Fx8 + else + return a + } + export function min(a: Fx8, b: Fx8) { + if (a < b) + return a + else + return b + } + export function max(a: Fx8, b: Fx8) { + if (a > b) + return a + else + return b + } + export function leftShift(a: Fx8, n: number) { + return (a as any as number << n) as any as Fx8 + } + export function rightShift(a: Fx8, n: number) { + return (a as any as number >> n) as any as Fx8 + } + export function toInt(v: Fx8) { + return ((v as any as number) + 128) >> 8 + } + export function toFloat(v: Fx8) { + return (v as any as number) / 256 + } +} \ No newline at end of file diff --git a/libs/base/forever.ts b/libs/base/forever.ts new file mode 100644 index 00000000..44b42c8f --- /dev/null +++ b/libs/base/forever.ts @@ -0,0 +1,18 @@ +/** + * Repeats the code forever in the background. On each iteration, allows other codes to run. + * @param body code to execute + */ +//% help=loops/forever weight=100 afterOnStart=true blockNamespace="loops" +//% blockId=forever block="forever" blockAllowMultiple=1 +function forever(a: () => void): void { + loops.forever(a); +} + +// micro:bit compatibility +// these functions allow some level of reuse +// between micro:bit and other maker-style editors +namespace basic { + export function forever(a: () => void) { + loops.forever(a); + } +} \ No newline at end of file diff --git a/libs/base/gc.cpp b/libs/base/gc.cpp new file mode 100644 index 00000000..d0834ec5 --- /dev/null +++ b/libs/base/gc.cpp @@ -0,0 +1,907 @@ +#include "pxtbase.h" + +#ifndef GC_BLOCK_SIZE +#define GC_BLOCK_SIZE (1024 * 16) +#endif + +#ifndef GC_MAX_ALLOC_SIZE +#define GC_MAX_ALLOC_SIZE (GC_BLOCK_SIZE - 16) +#endif + +#ifndef GC_ALLOC_BLOCK +#define GC_ALLOC_BLOCK xmalloc +#endif + +#ifdef PXT64 +#define HIGH_SHIFT 48 +#define BYTES_TO_WORDS(x) ((x) >> 3) +#define WORDS_TO_BYTES(x) ((x) << 3) +#define ALIGN_TO_WORD(x) (((x) + 7) & (~7ULL)) +#define VAR_BLOCK_WORDS(vt) ((uint32_t)(vt) >> 2) +#else +#define HIGH_SHIFT 28 +#define BYTES_TO_WORDS(x) ((x) >> 2) +#define WORDS_TO_BYTES(x) ((x) << 2) +#define ALIGN_TO_WORD(x) (((x) + 3) & (~3U)) +#define VAR_BLOCK_WORDS(vt) (((uint32_t)(vt) << 4) >> (4 + 2)) +#endif + +#define FREE_MASK (1ULL << (HIGH_SHIFT + 3)) +#define ARRAY_MASK (1ULL << (HIGH_SHIFT + 2)) +#define PERMA_MASK (1ULL << (HIGH_SHIFT + 1)) +#define MARKED_MASK 0x1 +#define ANY_MARKED_MASK 0x3 + +// the bit operations should be faster than loading large constants +#define IS_FREE(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 3)) +#define IS_ARRAY(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 2)) & 1) +#define IS_PERMA(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 1)) & 1) +#define IS_VAR_BLOCK(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 2)) +#define IS_MARKED(vt) ((uintptr_t)(vt)&MARKED_MASK) +#define IS_LIVE(vt) (IS_MARKED(vt) || (((uintptr_t)(vt) >> (HIGH_SHIFT)) == 0x6)) + +//#define PXT_GC_DEBUG 1 +#ifndef PXT_GC_CHECKS +#define PXT_GC_CHECKS 1 +#endif +//#define PXT_GC_STRESS 1 + +//#define PXT_GC_CHECKS 1 + +#define MARK(v) \ + do { \ + GC_CHECK(inGCArea(v), 42); \ + *(uintptr_t *)(v) |= MARKED_MASK; \ + } while (0) + +#ifdef PXT_GC_DEBUG +#define LOG DMESG +#define VLOG DMESG +#define VVLOG DMESG +#else +#define LOG NOLOG +#define VLOG NOLOG +#define VVLOG NOLOG +#endif + +#ifdef PXT_GC_CHECKS +#define GC_CHECK(cond, code) \ + if (!(cond)) \ + oops(code) +#else +#define GC_CHECK(cond, code) ((void)0) +#endif + +namespace pxt { + +// keep in sync with base/control.ts, function gcStats() +struct GCStats { + uint32_t numGC; + uint32_t numBlocks; + uint32_t totalBytes; + uint32_t lastFreeBytes; + uint32_t lastMaxBlockBytes; + uint32_t minFreeBytes; +}; + +static GCStats gcStats; + +//% expose +Buffer getGCStats() { + return mkBuffer((uint8_t *)&gcStats, sizeof(gcStats)); +} + +//% +void popThreadContext(ThreadContext *ctx); +//% +ThreadContext *pushThreadContext(void *sp, void *endSP); + +unsigned RefRecord_gcsize(RefRecord *r) { + VTable *tbl = getVTable(r); + return BYTES_TO_WORDS(tbl->numbytes); +} + +#ifdef PXT_GC_THREAD_LIST +ThreadContext *threadContexts; +#endif + +#define IN_GC_ALLOC 1 +#define IN_GC_COLLECT 2 +#define IN_GC_FREEZE 4 +#define IN_GC_PREALLOC 8 + +#ifndef PXT_VM +static TValue *tempRoot; +static uint8_t tempRootLen; +#endif + +uint8_t inGC; + +void popThreadContext(ThreadContext *ctx) { +#ifndef PXT_VM + VLOG("pop: %p", ctx); + + if (!ctx) + return; + + auto n = ctx->stack.next; + if (n) { + VLOG("seg %p", n); + ctx->stack.top = n->top; + ctx->stack.bottom = n->bottom; + ctx->stack.next = n->next; + app_free(n); + } else { +#ifdef PXT_GC_THREAD_LIST + if (ctx->next) + ctx->next->prev = ctx->prev; + if (ctx->prev) + ctx->prev->next = ctx->next; + else { + if (threadContexts != ctx) + oops(41); + threadContexts = ctx->next; + if (threadContexts) + threadContexts->prev = NULL; + } +#endif + app_free(ctx); + setThreadContext(NULL); + } +#endif +} + +#define ALLOC(tp) (tp *)app_alloc(sizeof(tp)) + +ThreadContext *pushThreadContext(void *sp, void *endSP) { +#ifdef PXT_VM + return NULL; +#else + if (PXT_IN_ISR()) + target_panic(PANIC_CALLED_FROM_ISR); + + auto curr = getThreadContext(); + tempRoot = (TValue *)endSP; + tempRootLen = (uintptr_t *)sp - (uintptr_t *)endSP; + if (curr) { +#ifdef PXT_GC_THREAD_LIST +#ifdef PXT_GC_DEBUG + auto ok = false; + for (auto p = threadContexts; p; p = p->next) + if (p == curr) { + ok = true; + break; + } + if (!ok) + oops(49); +#endif +#endif + auto seg = ALLOC(StackSegment); + VLOG("stack %p / %p", seg, curr); + seg->top = curr->stack.top; + seg->bottom = curr->stack.bottom; + seg->next = curr->stack.next; + curr->stack.next = seg; + } else { + curr = ALLOC(ThreadContext); + LOG("push: %p", curr); + curr->globals = globals; + curr->stack.next = NULL; + curr->thrownValue = TAG_NON_VALUE; + curr->tryFrame = NULL; + +#ifdef PXT_GC_THREAD_LIST + curr->next = threadContexts; + curr->prev = NULL; + if (curr->next) + curr->next->prev = curr; + threadContexts = curr; +#endif + setThreadContext(curr); + } + tempRootLen = 0; + curr->stack.bottom = sp; + curr->stack.top = NULL; + return curr; +#endif +} + +class RefBlock : public RefObject { + public: + RefBlock *nextFree; +}; + +struct GCBlock { + GCBlock *next; + uint32_t blockSize; + RefObject data[0]; +}; + +struct PendingArray { + PendingArray *next; + TValue *data; + unsigned len; +}; + +#define PENDING_ARRAY_THR 100 + +static PendingArray *pendingArrays; +static LLSegment gcRoots; +LLSegment workQueue; // (ab)used by consString making +static GCBlock *firstBlock; +static RefBlock *firstFree; +static uint8_t *midPtr; + +static bool inGCArea(void *ptr) { + for (auto block = firstBlock; block; block = block->next) { + if ((void *)block->data <= ptr && ptr < (void *)((uint8_t *)block->data + block->blockSize)) + return true; + } + return false; +} + +#define NO_MAGIC(vt) ((VTable *)vt)->magic != VTABLE_MAGIC +#define VT(p) (*(uintptr_t *)(p)) +#define SKIP_PROCESSING(p) \ + (isReadOnly(p) || (VT(p) & (ANY_MARKED_MASK | ARRAY_MASK)) || NO_MAGIC(VT(p))) + +void gcMarkArray(void *data) { + auto segBl = (uintptr_t *)data - 1; + GC_CHECK(!IS_MARKED(VT(segBl)), 47); + MARK(segBl); +} + +void gcScan(TValue v) { + if (SKIP_PROCESSING(v)) + return; + MARK(v); + workQueue.push(v); +} + +void gcScanMany(TValue *data, unsigned len) { + // VLOG("scan: %p %d", data, len); + for (unsigned i = 0; i < len; ++i) { + auto v = data[i]; + // VLOG("psh: %p %d %d", v, isReadOnly(v), (*(uint32_t *)v & 1)); + if (SKIP_PROCESSING(v)) + continue; + MARK(v); + workQueue.push(v); + if (workQueue.getLength() > PENDING_ARRAY_THR) { + i++; + // store rest of the work for later, when we have cleared the queue + auto pa = (PendingArray *)xmalloc(sizeof(PendingArray)); + pa->next = pendingArrays; + pa->data = data + i; + pa->len = len - i; + pendingArrays = pa; + break; + } + } +} + +void gcScanSegment(Segment &seg) { + auto data = seg.getData(); + if (!data) + return; + VVLOG("seg %p %d", data, seg.getLength()); + gcMarkArray(data); + gcScanMany(data, seg.getLength()); +} + +#define getScanMethod(vt) ((RefObjectMethod)(((VTable *)(vt))->methods[2])) +#define getSizeMethod(vt) ((RefObjectSizeMethod)(((VTable *)(vt))->methods[3])) + +void gcProcess(TValue v) { + if (SKIP_PROCESSING(v)) + return; + VVLOG("gcProcess: %p", v); + MARK(v); + auto scan = getScanMethod(VT(v) & ~ANY_MARKED_MASK); + if (scan) + scan((RefObject *)v); + for (;;) { + while (workQueue.getLength()) { + auto curr = (RefObject *)workQueue.pop(); + VVLOG(" - %p", curr); + scan = getScanMethod(curr->vt() & ~ANY_MARKED_MASK); + if (scan) + scan(curr); + } + if (pendingArrays) { + auto pa = pendingArrays; + pendingArrays = pa->next; + auto data = pa->data; + auto len = pa->len; + xfree(pa); + gcScanMany(data, len); + } else { + break; + } + } +} + +static void mark(int flags) { +#ifdef PXT_GC_DEBUG + flags |= 2; +#endif + auto data = gcRoots.getData(); + auto len = gcRoots.getLength(); + if (flags & 2) { + DMESG("--MARK"); + DMESG("RP:%p/%d", data, len); + } + for (unsigned i = 0; i < len; ++i) { + auto d = data[i]; + if ((uintptr_t)d & 1) { + d = *(TValue *)((uintptr_t)d & ~1); + } + gcProcess(d); + } + +#ifdef PXT_GC_THREAD_LIST + for (auto ctx = threadContexts; ctx; ctx = ctx->next) { + gcProcess(ctx->thrownValue); + for (auto seg = &ctx->stack; seg; seg = seg->next) { + auto ptr = (TValue *)threadAddressFor(ctx, seg->top); + auto end = (TValue *)threadAddressFor(ctx, seg->bottom); + VLOG("mark: %p - %p", ptr, end); + while (ptr < end) { + gcProcess(*ptr++); + } + } + } +#else + gcProcessStacks(flags); +#endif + + if (globals) { +#ifdef PXT_VM + auto nonPtrs = vmImg->infoHeader->nonPointerGlobals; +#else + auto nonPtrs = bytecode[21]; +#endif + len = getNumGlobals() - nonPtrs; + data = globals + nonPtrs; + if (flags & 2) + DMESG("RG:%p/%d", data, len); + VLOG("globals: %p %d", data, len); + for (unsigned i = 0; i < len; ++i) { + gcProcess(*data++); + } + } + +#ifndef PXT_VM + data = tempRoot; + len = tempRootLen; + for (unsigned i = 0; i < len; ++i) { + gcProcess(*data++); + } +#endif +} + +static uint32_t getObjectSize(RefObject *o) { + auto vt = o->vt() & ~ANY_MARKED_MASK; + uint32_t r; + GC_CHECK(vt != 0, 49); + if (IS_VAR_BLOCK(vt)) { + r = VAR_BLOCK_WORDS(vt); + } else { + auto sz = getSizeMethod(vt); + // GC_CHECK(0x2000 <= (intptr_t)sz && (intptr_t)sz <= 0x100000, 47); + r = sz(o); + } + GC_CHECK(1 <= r && (r <= BYTES_TO_WORDS(GC_MAX_ALLOC_SIZE) || IS_FREE(vt)), 41); + return r; +} + +static void setupFreeBlock(GCBlock *curr) { + gcStats.numBlocks++; + gcStats.totalBytes += curr->blockSize; + curr->data[0].setVT(FREE_MASK | (TOWORDS(curr->blockSize) << 2)); + ((RefBlock *)curr->data)[0].nextFree = firstFree; + firstFree = (RefBlock *)curr->data; + midPtr = (uint8_t *)curr->data + curr->blockSize / 4; +} + +static void linkFreeBlock(GCBlock *curr) { + // blocks need to be sorted by address for midPtr to work + if (!firstBlock || curr < firstBlock) { + curr->next = firstBlock; + firstBlock = curr; + } else { + for (auto p = firstBlock; p; p = p->next) { + if (!p->next || curr < p->next) { + curr->next = p->next; + p->next = curr; + break; + } + } + } +} + +void gcPreAllocateBlock(uint32_t sz) { + auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz); + curr->blockSize = sz - sizeof(GCBlock); + LOG("GC pre-alloc: %p", curr); + GC_CHECK((curr->blockSize & 3) == 0, 40); + setupFreeBlock(curr); + linkFreeBlock(curr); +} + +static GCBlock *allocateBlockCore() { + int sz = GC_BLOCK_SIZE; + void *dummy = NULL; +#ifdef GC_GET_HEAP_SIZE + if (firstBlock) { +#ifdef GC_STACK_BASE + if (!firstBlock->next) { + int memSize = getConfig(CFG_RAM_BYTES, 0); + int codalEnd = GC_STACK_BASE; + // round up to 1k - there is sometimes a few bytes below the stack + codalEnd = (codalEnd + 1024) & ~1023; + int codalSize = codalEnd & 0xffffff; + sz = memSize - codalSize - 4; + if (sz > 0) { + auto curr = (GCBlock *)codalEnd; + curr->blockSize = sz - sizeof(GCBlock); + return curr; + } + } +#endif + gc(2); // dump roots + target_panic(PANIC_GC_OOM); + } + auto lowMem = getConfig(CFG_LOW_MEM_SIMULATION_KB, 0); + auto sysHeapSize = getConfig(CFG_SYSTEM_HEAP_BYTES, 4 * 1024); + auto heapSize = GC_GET_HEAP_SIZE(); + sz = heapSize - sysHeapSize; + if (lowMem) { + auto memIncrement = 32 * 1024; + // get the memory size - assume it's increment of 32k, + // and we don't statically allocate more than 32k + auto memSize = ((heapSize + memIncrement - 1) / memIncrement) * memIncrement; + int fillerSize = memSize - lowMem * 1024; + if (fillerSize > 0) { + dummy = GC_ALLOC_BLOCK(fillerSize); + sz -= fillerSize; + } + } +#endif + auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz); + curr->blockSize = sz - sizeof(GCBlock); + // make sure reference to allocated block is stored somewhere, otherwise + // GCC optimizes out the call to GC_ALLOC_BLOCK + curr->data[4].setVT((uintptr_t)dummy); + return curr; +} + +__attribute__((noinline)) static void allocateBlock() { + auto curr = allocateBlockCore(); + DMESG("GC block %db @ %p", curr->blockSize, curr); + GC_CHECK((curr->blockSize & 3) == 0, 40); + setupFreeBlock(curr); + linkFreeBlock(curr); +} + +static void sweep(int flags) { + RefBlock *prevFreePtr = NULL; + uint32_t freeSize = 0; + uint32_t totalSize = 0; + uint32_t maxFreeBlock = 0; + firstFree = NULL; + + gcStats.numGC++; + + for (auto h = firstBlock; h; h = h->next) { + auto d = h->data; + auto words = BYTES_TO_WORDS(h->blockSize); + auto end = d + words; + totalSize += words; + VLOG("sweep: %p - %p", d, end); + while (d < end) { + if (IS_LIVE(d->vtable)) { + VVLOG("Live %p", d); + d->setVT(d->vt() & ~MARKED_MASK); + d += getObjectSize(d); + } else { + auto start = (RefBlock *)d; + while (d < end) { + if (IS_FREE(d->vtable)) { + VVLOG("Free %p", d); + } else if (IS_LIVE(d->vtable)) { + break; + } else if (IS_ARRAY(d->vtable)) { + VVLOG("Dead Arr %p", d); + } else { + VVLOG("Dead Obj %p", d); + GC_CHECK(d->vtable->magic == VTABLE_MAGIC, 41); + d->destroyVT(); + VVLOG("destroyed"); + } + d += getObjectSize(d); + } + auto sz = d - (RefObject *)start; + freeSize += sz; + if (sz > (int)maxFreeBlock) + maxFreeBlock = sz; +#ifdef PXT_GC_CHECKS + memset((void *)start, 0xff, WORDS_TO_BYTES(sz)); +#endif + start->setVT((sz << 2) | FREE_MASK); + if (sz > 1) { + start->nextFree = NULL; + if (!prevFreePtr) { + firstFree = start; + } else { + prevFreePtr->nextFree = start; + } + prevFreePtr = start; + } + } + } + } + + if (midPtr) { + uint32_t currFree = 0; + auto limit = freeSize * 1 / 2; + for (auto p = firstFree; p; p = p->nextFree) { + auto len = VAR_BLOCK_WORDS(p->vtable); + currFree += len; + if (currFree > limit) { + midPtr = (uint8_t *)p + ((limit - currFree + len) << 2); + break; + } + } + } + + freeSize = WORDS_TO_BYTES(freeSize); + totalSize = WORDS_TO_BYTES(totalSize); + maxFreeBlock = WORDS_TO_BYTES(maxFreeBlock); + + gcStats.lastFreeBytes = freeSize; + gcStats.lastMaxBlockBytes = maxFreeBlock; + + if (gcStats.minFreeBytes == 0 || gcStats.minFreeBytes > freeSize) + gcStats.minFreeBytes = freeSize; + + if (flags & 1) + DMESG("GC %d/%d free; %d maxBlock", freeSize, totalSize, maxFreeBlock); + else + LOG("GC %d/%d free; %d maxBlock", freeSize, totalSize, maxFreeBlock); + +#ifndef GC_GET_HEAP_SIZE + // if the heap is 90% full, allocate a new block + if (freeSize * 10 <= totalSize) { + allocateBlock(); + } +#endif +} + +void gc(int flags) { + startPerfCounter(PerfCounters::GC); + GC_CHECK(!(inGC & IN_GC_COLLECT), 40); + inGC |= IN_GC_COLLECT; + VLOG("GC mark"); + mark(flags); + VLOG("GC sweep"); + sweep(flags); + VLOG("GC done"); + stopPerfCounter(PerfCounters::GC); + inGC &= ~IN_GC_COLLECT; +} + +#ifdef GC_GET_HEAP_SIZE +extern "C" void free(void *ptr) { + if (!ptr) + return; + if (inGCArea(ptr)) + app_free(ptr); + else + xfree(ptr); +} + +extern "C" void *malloc(size_t sz) { + if (PXT_IN_ISR() || inGC) + return xmalloc(sz); + else + return app_alloc(sz); +} + +extern "C" void *realloc(void *ptr, size_t size) { + if (inGCArea(ptr)) { + void *mem = malloc(size); + + if (ptr != NULL && mem != NULL) { + auto r = (uintptr_t *)ptr; + GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41); + size_t blockSize = VAR_BLOCK_WORDS(r[-1]); + memcpy(mem, ptr, min(blockSize * sizeof(void *), size)); + free(ptr); + } + + return mem; + } else { + return device_realloc(ptr, size); + } +} +#endif + +void *gcAllocateArray(int numbytes) { + numbytes = ALIGN_TO_WORD(numbytes); + numbytes += sizeof(void *); + auto r = (uintptr_t *)gcAllocate(numbytes); + *r = ARRAY_MASK | (TOWORDS(numbytes) << 2); + return r + 1; +} + +static void *gcAllocAt(void *hint, int numbytes) { + gc(0); + size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes)); + + for (auto p = firstFree; p; p = p->nextFree) { + GC_CHECK(!isReadOnly((TValue)p), 49); + auto vt = p->vtable; + GC_CHECK(IS_FREE(vt), 43); + int offset = BYTES_TO_WORDS((uint8_t *)hint - (uint8_t *)p); + int left = (int)(VAR_BLOCK_WORDS(vt) - numwords - offset); + // we give ourselves some space here, so we don't get some strange overlaps + if (offset >= 8 && left >= 8) { + auto nf = (RefBlock *)((void **)p + numwords + offset); + nf->setVT((left << 2) | FREE_MASK); + nf->nextFree = p->nextFree; + p->nextFree = nf; + p->setVT((offset << 2) | FREE_MASK); + p = (RefBlock *)((void **)p + offset); + p->setVT(0); + return p; + } + } + + return NULL; +} + +void *app_alloc_at(void *at, int numbytes) { + if (numbytes < 8) + return NULL; + if (!at) + return NULL; + + numbytes = ALIGN_TO_WORD(numbytes) + sizeof(void *); + auto r = (uintptr_t *)gcAllocAt((uintptr_t *)at - 1, numbytes); + if (!r) + return NULL; + *r = ARRAY_MASK | PERMA_MASK | (TOWORDS(numbytes) << 2); + gc(0); + return r + 1; +} + +void *app_alloc(int numbytes) { + if (!numbytes) + return NULL; + + // gc(0); + auto r = (uintptr_t *)gcAllocateArray(numbytes); + r[-1] |= PERMA_MASK; + return r; +} + +void *app_free(void *ptr) { + auto r = (uintptr_t *)ptr; + GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41); + r[-1] |= FREE_MASK; + return r; +} + +void gcFreeze() { + inGC |= IN_GC_FREEZE; +} + +void gcReset() { + inGC &= ~IN_GC_FREEZE; + + gcRoots.setLength(0); + + if (inGC) + oops(41); + + if (workQueue.getLength()) + oops(41); + + memset(&gcStats, 0, sizeof(gcStats)); + firstFree = NULL; + for (auto h = firstBlock; h; h = h->next) { + setupFreeBlock(h); + } +} + +#ifdef PXT_VM +void gcPreStartup() { + inGC |= IN_GC_PREALLOC; +} + +void gcStartup() { + inGC &= ~IN_GC_PREALLOC; +} +#endif + +void *gcAllocate(int numbytes) { + size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes)); + // VVLOG("alloc %d bytes %d words", numbytes, numwords); + + if (numbytes > GC_MAX_ALLOC_SIZE) + target_panic(PANIC_GC_TOO_BIG_ALLOCATION); + + if (PXT_IN_ISR() || (inGC & (IN_GC_PREALLOC | IN_GC_ALLOC | IN_GC_COLLECT | IN_GC_FREEZE))) + target_panic(PANIC_CALLED_FROM_ISR); + + inGC |= IN_GC_ALLOC; + +#if defined(PXT_GC_CHECKS) && !defined(PXT_VM) + { + auto curr = getThreadContext(); + if (curr && !curr->stack.top) + oops(46); + } +#endif + +#ifdef PXT_GC_STRESS + gc(0); +#endif + + for (int i = 0;; ++i) { + RefBlock *prev = NULL; + for (auto p = firstFree; p; p = p->nextFree) { + VVLOG("p=%p", p); + if (i == 0 && (uint8_t *)p > midPtr) { + VLOG("past midptr %p; gc", midPtr); + break; + } + GC_CHECK(!isReadOnly((TValue)p), 49); + auto vt = p->vtable; + if (!IS_FREE(vt)) + oops(43); + int left = (int)(VAR_BLOCK_WORDS(vt) - numwords); + VVLOG("%p %d - %d = %d", (void *)vt, (int)VAR_BLOCK_WORDS(vt), (int)numwords, left); + if (left >= 0) { + auto nf = (RefBlock *)((void **)p + numwords); + auto nextFree = p->nextFree; // p and nf can overlap when allocating 4 bytes + // VVLOG("nf=%p nef=%p", nf, nextFree); + if (left) + nf->setVT((left << 2) | FREE_MASK); + if (left >= 2) { + nf->nextFree = nextFree; + } else { + nf = nextFree; + } + if (prev) + prev->nextFree = nf; + else + firstFree = nf; + p->setVT(0); + VVLOG("GC=>%p %d %p -> %p,%p", p, numwords, nf, nf ? nf->nextFree : 0, + nf ? (void *)nf->vtable : 0); + GC_CHECK(!nf || !nf->nextFree || !isReadOnly((TValue)nf->nextFree), 48); + inGC &= ~IN_GC_ALLOC; + return p; + } + prev = p; + } + + // we didn't find anything, try GC + if (i == 0) + gc(0); + // GC didn't help, try new block + else if (i == 1) + allocateBlock(); + else + // the block allocated was apparently too small + target_panic(PANIC_GC_OOM); + } +} + +static void removePtr(TValue v) { + int len = gcRoots.getLength(); + auto data = gcRoots.getData(); + // scan from the back, as this is often used as a stack + for (int i = len - 1; i >= 0; --i) { + if (data[i] == v) { + if (i == len - 1) { + gcRoots.pop(); + } else { + data[i] = gcRoots.pop(); + } + return; + } + } + oops(40); +} + +void registerGC(TValue *root, int numwords) { + if (!numwords) + return; + + if (numwords > 1) { + while (numwords-- > 0) { + registerGC(root++, 1); + } + return; + } + + gcRoots.push((TValue)((uintptr_t)root | 1)); +} + +void unregisterGC(TValue *root, int numwords) { + if (!numwords) + return; + if (numwords > 1) { + while (numwords-- > 0) { + unregisterGC(root++, 1); + } + return; + } + + removePtr((TValue)((uintptr_t)root | 1)); +} + +void registerGCPtr(TValue ptr) { + if (isReadOnly(ptr)) + return; + gcRoots.push(ptr); +} + +void unregisterGCPtr(TValue ptr) { + if (isReadOnly(ptr)) + return; + removePtr(ptr); +} + +void RefImage::scan(RefImage *t) { + gcScan((TValue)t->buffer); +} + +void RefCollection::scan(RefCollection *t) { + gcScanSegment(t->head); +} + +void RefAction::scan(RefAction *t) { + gcScanMany(t->fields, t->len); +} + +void RefRefLocal::scan(RefRefLocal *t) { + gcScan(t->v); +} + +void RefMap::scan(RefMap *t) { + gcScanSegment(t->keys); + gcScanSegment(t->values); +} + +void RefRecord_scan(RefRecord *r) { + VTable *tbl = getVTable(r); + gcScanMany(r->fields, BYTES_TO_WORDS(tbl->numbytes - sizeof(RefRecord))); +} + +#define SIZE(off) TOWORDS(sizeof(*t) + (off)) + +unsigned RefImage::gcsize(RefImage *t) { + return SIZE(0); +} + +unsigned RefCollection::gcsize(RefCollection *t) { + return SIZE(0); +} + +unsigned RefAction::gcsize(RefAction *t) { + return SIZE(WORDS_TO_BYTES(t->len)); +} + +unsigned RefRefLocal::gcsize(RefRefLocal *t) { + return SIZE(0); +} + +unsigned RefMap::gcsize(RefMap *t) { + return SIZE(0); +} + +} // namespace pxt diff --git a/libs/base/gcstats.ts b/libs/base/gcstats.ts new file mode 100644 index 00000000..3dd3a79c --- /dev/null +++ b/libs/base/gcstats.ts @@ -0,0 +1,40 @@ +namespace control { + //% shim=pxt::getGCStats + function getGCStats(): Buffer { + return null + } + + export interface GCStats { + numGC: number; + numBlocks: number; + totalBytes: number; + lastFreeBytes: number; + lastMaxBlockBytes: number; + minFreeBytes: number; + } + + /** + * Get various statistics about the garbage collector (GC) + */ + export function gcStats(): GCStats { + const buf = getGCStats() + if (!buf) + return null + let off = 0 + const res: any = {} + + addField("numGC") + addField("numBlocks") + addField("totalBytes") + addField("lastFreeBytes") + addField("lastMaxBlockBytes") + addField("minFreeBytes") + + return res + + function addField(name: string) { + res[name] = buf.getNumber(NumberFormat.UInt32LE, off) + off += 4 + } + } +} \ No newline at end of file diff --git a/libs/base/interval.ts b/libs/base/interval.ts new file mode 100644 index 00000000..459adef0 --- /dev/null +++ b/libs/base/interval.ts @@ -0,0 +1,72 @@ +namespace control { + export enum IntervalMode { + Interval, + Timeout, + Immediate + } + + let _intervals: Interval[] = undefined; + class Interval { + + id: number; + func: () => void; + delay: number; + mode: IntervalMode; + + constructor(func: () => void, delay: number, mode: IntervalMode) { + this.id = _intervals.length == 0 + ? 1 : _intervals[_intervals.length - 1].id + 1; + this.func = func; + this.delay = delay; + this.mode = mode; + _intervals.push(this); + + control.runInParallel(() => this.work()); + } + + work() { + // execute + switch (this.mode) { + case IntervalMode.Immediate: + case IntervalMode.Timeout: + if (this.delay > 0) + pause(this.delay); // timeout + if (this.delay >= 0) // immediate, timeout + this.func(); + break; + case IntervalMode.Interval: + while (this.delay > 0) { + pause(this.delay); + // might have been cancelled during this duration + if (this.delay > 0) + this.func(); + } + break; + } + // remove from interval array + _intervals.removeElement(this); + } + + cancel() { + this.delay = -1; + } + } + + export function setInterval(func: () => void, delay: number, mode: IntervalMode): number { + if (!func || delay < 0) return 0; + if (!_intervals) _intervals = []; + const interval = new Interval(func, delay, mode); + return interval.id; + } + + export function clearInterval(intervalId: number, mode: IntervalMode): void { + if (!_intervals) return; + for (let i = 0; i < _intervals.length; ++i) { + const it = _intervals[i]; + if (it.id == intervalId && it.mode == mode) { + it.cancel(); + break; + } + } + } +} \ No newline at end of file diff --git a/libs/base/json.ts b/libs/base/json.ts new file mode 100644 index 00000000..99d51bd7 --- /dev/null +++ b/libs/base/json.ts @@ -0,0 +1,322 @@ +namespace JSON { + export function parseIntRadix(s: string, base?: number) { + if (base == null || base == 10) { + return parseFloat(s) | 0 + } + + let m = false + let r = 0 + for (let i = 0; i < s.length; ++i) { + let c = s.charCodeAt(i) + if (c == 0x20 || c == 10 || c == 13 || c == 9) + continue + if (r == 0 && !m && c == 0x2d) { + m = true + continue + } + + let v = -1 + if (0x30 <= c && c <= 0x39) + v = c - 0x30 + else { + c |= 0x20 + if (0x61 <= c && c <= 0x7a) + v = c - 0x61 + 10 + } + + if (0 <= v && v < base) { + r *= base + r += v + } else { + return undefined + } + } + + return m ? -r : r + } + + + class Parser { + ptr: number + s: string + errorMsg: string + + error(msg: string) { + if (!this.errorMsg) { + this.errorMsg = msg + " at position " + this.ptr + this.ptr = this.s.length + } + } + + skipWS() { + for (; ;) { + const c = this.nextChar() + if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09) { + // OK + } else { + this.ptr-- + return c + } + } + } + + nextChar() { + if (this.ptr < this.s.length) + return this.s.charCodeAt(this.ptr++) + return 0 + } + + doString() { + let r = "" + this.ptr++ + for (; ;) { + const c = this.s.charAt(this.ptr++) + if (c == "\"") + return r + if (c == "\\") { + let q = this.s.charAt(this.ptr++) + if (q == "b") q = "\b" + else if (q == "n") q = "\n" + else if (q == "r") q = "\r" + else if (q == "t") q = "\t" + else if (q == "u") { + q = String.fromCharCode(parseIntRadix(this.s.slice(this.ptr, this.ptr + 4), 16)) + this.ptr += 4 + } + r += q + } else { + r += c + } + } + } + + doArray(): any[] { + const r = [] + this.ptr++ + for (; ;) { + let c = this.skipWS() + if (c == 0x5d) { + this.ptr++ + return r + } + const v = this.value() + if (this.errorMsg) + return null + r.push(v) + c = this.skipWS() + if (c == 0x2c) { + this.ptr++ + continue + } + if (c == 0x5d) + continue + this.error("expecting comma") + } + } + + doObject() { + const r: any = {} + this.ptr++ + for (; ;) { + let c = this.skipWS() + if (c == 0x7d) { + this.ptr++ + return r + } + if (c != 0x22) { + this.error("expecting key") + return r + } + const k = this.doString() + c = this.skipWS() + if (c != 0x3a) { + this.error("expecting colon") + return r + } + this.ptr++ + const v = this.value() + if (this.errorMsg) + return null + r[k] = v + c = this.skipWS() + if (c == 0x2c) { + this.ptr++ + continue + } + if (c == 0x7d) + continue + this.error("expecting comma, got " + String.fromCharCode(c)) + } + } + + doNumber() { + const beg = this.ptr + for (; ;) { + const c = this.nextChar() + if ((0x30 <= c && c <= 0x39) || c == 0x2b || c == 0x2d || c == 0x2e || c == 0x45 || c == 0x65) { + // one more + } else { + this.ptr-- + break + } + } + const ss = this.s.slice(beg, this.ptr) + if (ss.length == 0) { + this.error("expecting number") + return 0 + } + return parseFloat(ss) + } + + checkKw(k: string) { + if (this.s.slice(this.ptr, this.ptr + k.length) == k) { + this.ptr += k.length + return true + } + return false + } + + value() { + if (this.errorMsg) + return null + + const c = this.skipWS() + if (c == 0x7b) + return this.doObject() + else if (c == 0x5b) + return this.doArray() + else if ((0x30 <= c && c <= 0x39) || c == 0x2d) + return this.doNumber() + else if (c == 0x22) + return this.doString() + else if (c == 0x74 && this.checkKw("true")) + return true + else if (c == 0x66 && this.checkKw("false")) + return false + else if (c == 0x6e && this.checkKw("null")) + return null + + this.error("unexpected token") + return null + } + } + + class Stringifier { + currIndent: string + indentStep: string + indent: number + + doString(s: string) { + let r = "\"" + for (let i = 0; i < s.length; ++i) { + let c = s[i] + if (c == "\n") c = "\\n" + else if (c == "\r") c = "\\r" + else if (c == "\t") c = "\\t" + else if (c == "\b") c = "\\b" + else if (c == "\\") c = "\\\\" + else if (c == "\"") c = "\\\"" + r += c + } + return r + "\"" + } + + go(v: any) { + const t = typeof v + if (t == "string") + return this.doString(v) + else if (t == "boolean" || t == "number" || v == null) + return "" + v + else if (Array.isArray(v)) { + const arr = v as any[] + if (arr.length == 0) + return "[]" + else { + let r = "[" + if (this.indent) { + this.currIndent += this.indentStep + r += "\n" + } + for (let i = 0; i < arr.length; ++i) { + r += this.currIndent + this.go(arr[i]) + if (i != arr.length - 1) + r += "," + if (this.indent) + r += "\n" + } + if (this.indent) + this.currIndent = this.currIndent.slice(this.indent) + r += this.currIndent + "]" + return r + } + } else { + const keys = Object.keys(v) + if (keys.length == 0) + return "{}" + + let r = "{" + if (this.indent) { + this.currIndent += this.indentStep + r += "\n" + } + for (let i = 0; i < keys.length; ++i) { + const k = keys[i] + r += this.currIndent + this.doString(k) + if (this.indent) + r += ": " + else + r += ":" + r += this.go(v[k]) + if (i != keys.length - 1) + r += "," + if (this.indent) + r += "\n" + } + if (this.indent) + this.currIndent = this.currIndent.slice(this.indent) + r += this.currIndent + "}" + return r + } + } + } + + /** + * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. + * @param value A JavaScript value, usually an object or array, to be converted. + * @param replacer Not supported; use null. + * @param indent Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. + */ + export function stringify(value: any, replacer: any = null, indent: number = 0) { + const ss = new Stringifier() + ss.currIndent = "" + indent |= 0 + if (indent < 0) indent = 0 + if (indent > 10) indent = 10 + ss.indentStep = "" + ss.currIndent = "" + ss.indent = indent + while (indent-- > 0) + ss.indentStep += " " + return ss.go(value) + } + + + /** + * Converts a JavaScript Object Notation (JSON) string into an object. + * @param text A valid JSON string. + */ + export function parse(s: string) { + const p = new Parser() + p.ptr = 0 + p.s = s + const r = p.value() + if (p.skipWS()) { + p.error("excessive input") + } + if (p.errorMsg) { + control.dmesg("Invalid JSON: " + p.errorMsg) + return undefined + } + return r + } +} diff --git a/libs/base/loops.cpp b/libs/base/loops.cpp new file mode 100644 index 00000000..47306ba2 --- /dev/null +++ b/libs/base/loops.cpp @@ -0,0 +1,27 @@ +#include "pxtbase.h" + +namespace loops { + +/** + * Repeats the code forever in the background. On each iteration, allows other codes to run. + * @param body code to execute + */ +//% help=loops/forever weight=100 afterOnStart=true deprecated=true +//% blockId=forever_deprecated block="forever" blockAllowMultiple=1 +void forever(Action a) { + runForever(a); +} + +/** + * Pause for the specified time in milliseconds + * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000 + */ +//% help=loops/pause weight=99 deprecated=true +//% async block="pause %pause=timePicker|ms" +//% blockId=device_pause_deprecated +void pause(int ms) { + if (ms < 0) return; + sleep_ms(ms); +} + +} \ No newline at end of file diff --git a/libs/base/math.ts b/libs/base/math.ts new file mode 100644 index 00000000..deafef0e --- /dev/null +++ b/libs/base/math.ts @@ -0,0 +1,83 @@ +namespace Math { + + export const E = 2.718281828459045; + export const LN2 = 0.6931471805599453; + export const LN10 = 2.302585092994046; + export const LOG2E = 1.4426950408889634; + export const LOG10E = 0.4342944819032518; + export const PI = 3.141592653589793; + export const SQRT1_2 = 0.7071067811865476; + export const SQRT2 = 1.4142135623730951; + + /** + * Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc. + * @param value value to map in ranges + * @param fromLow the lower bound of the value's current range + * @param fromHigh the upper bound of the value's current range, eg: 1023 + * @param toLow the lower bound of the value's target range + * @param toHigh the upper bound of the value's target range, eg: 4 + */ + //% help=math/map weight=10 blockGap=8 + //% blockId=math_map block="map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh" + //% inlineInputMode=inline + export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number { + return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow; + } + + /** + * Constrains a number to be within a range + * @param x the number to constrain, all data types + * @param y the lower end of the range, all data types + * @param z the upper end of the range, all data types + */ + //% help=math/constrain weight=11 blockGap=8 + //% blockId="math_constrain_value" block="constrain %value|between %low|and %high" + export function constrain(value: number, low: number, high: number): number { + return value < low ? low : value > high ? high : value; + } + + const b_m16: number[] = [0, 49, 49, 41, 90, 27, 117, 10] + /** + * Returns the sine of an input angle. This is an 8-bit approximation. + * @param theta input angle from 0-255 + */ + //% help=math/isin weight=11 advanced=true blockGap=8 + export function isin(theta: number) { + //reference: based on FASTLed's sin approximation method: [https://github.com/FastLED/FastLED](MIT) + let offset = theta; + if( theta & 0x40 ) { + offset = 255 - offset; + } + offset &= 0x3F; // 0..63 + + let secoffset = offset & 0x0F; // 0..15 + if( theta & 0x40) secoffset++; + + let section = offset >> 4; // 0..3 + let s2 = section * 2; + + let b = b_m16[s2]; + let m16 = b_m16[s2+1]; + let mx = (m16 * secoffset) >> 4; + + let y = mx + b; + if( theta & 0x80 ) y = -y; + + y += 128; + + return y; + } + + /** + * Returns the cosine of an input angle. This is an 8-bit approximation. + * @param theta input angle from 0-255 + */ + //% help=math/icos weight=10 advanced=true blockGap=8 + export function icos(theta: number) { + return isin(theta + 16384); + } +} + +namespace Number { + export const EPSILON = 2.220446049250313e-16; +} \ No newline at end of file diff --git a/libs/base/ns.ts b/libs/base/ns.ts new file mode 100644 index 00000000..e478a275 --- /dev/null +++ b/libs/base/ns.ts @@ -0,0 +1,7 @@ + +/** + * Respond to and read data from buttons and sensors. + */ +//% color="#B4009E" weight=98 icon="\uf192" +namespace input { +} diff --git a/libs/base/pause.ts b/libs/base/pause.ts new file mode 100644 index 00000000..60df5afd --- /dev/null +++ b/libs/base/pause.ts @@ -0,0 +1,19 @@ +/** + * Pause for the specified time in milliseconds + * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000 + */ +//% help=loops/pause weight=99 +//% async block="pause %pause=timePicker|ms" +//% blockId=device_pause blockNamespace="loops" +function pause(ms: number): void { + loops.pause(ms); +} + +// micro:bit compatibility +// these functions allow some level of reuse +// between micro:bit and other maker-style editors +namespace basic { + export function pause(millis: number) { + loops.pause(millis); + } +} \ No newline at end of file diff --git a/libs/base/perfcounters.ts b/libs/base/perfcounters.ts new file mode 100644 index 00000000..d16779f4 --- /dev/null +++ b/libs/base/perfcounters.ts @@ -0,0 +1,13 @@ +namespace control { + /** + * Enable profiling for current function. + */ + //% shim=TD_NOOP shimArgument=perfCounter + export function enablePerfCounter(name?: string) { } + + /** + * Dump values of profiling performance counters. + */ + //% shim=pxt::dumpPerfCounters + export function dmesgPerfCounters() { } +} diff --git a/libs/base/poll.ts b/libs/base/poll.ts new file mode 100644 index 00000000..47c8e5ab --- /dev/null +++ b/libs/base/poll.ts @@ -0,0 +1,78 @@ +namespace control { + class PollEvent { + public eid: number; + public vid: number; + public start: number; + public timeOut: number; + public condition: () => boolean; + public once: boolean; + constructor(eid: number, vid: number, start: number, timeOut: number, condition: () => boolean, once: boolean) { + this.eid = eid; + this.vid = vid; + this.start = start; + this.timeOut = timeOut; + this.condition = condition; + this.once = once; + } + } + + let _pollEventQueue: PollEvent[] = undefined; + + function pollEvents() { + while (_pollEventQueue.length > 0) { + const now = control.millis(); + for (let i = 0; i < _pollEventQueue.length; ++i) { + const ev = _pollEventQueue[i]; + if (ev.condition() || (ev.timeOut > 0 && now - ev.start > ev.timeOut)) { + control.raiseEvent(ev.eid, ev.vid); + if (ev.once) { + _pollEventQueue.splice(i, 1); + --i; + } + } + } + pause(50); + } + // release fiber + _pollEventQueue = undefined; + } + + export function __queuePollEvent(timeOut: number, condition: () => boolean, handler: () => void) { + const ev = new PollEvent( + control.allocateNotifyEvent(), + 1, + control.millis(), + timeOut, + condition, + !handler + ); + + // start polling fiber if needed + if (!_pollEventQueue) { + _pollEventQueue = [ev]; + control.runInParallel(pollEvents); + } + else { + // add to the queue + _pollEventQueue.push(ev) + } + + // register event + if (handler) + control.onEvent(ev.eid, ev.vid, handler); + else // or wait + control.waitForEvent(ev.eid, ev.vid); + } +} + +/** + * Busy wait for a condition to be true + * @param condition condition to test for + * @param timeOut if positive, maximum duration to wait for in milliseconds + */ +//% blockId="pxt_pause_until" +function pauseUntil(condition: () => boolean, timeOut?: number): void { + if (!condition || condition()) return; // optimistic path + if (!timeOut) timeOut = 0; + control.__queuePollEvent(timeOut, condition, undefined); +} diff --git a/libs/base/pxt.cpp b/libs/base/pxt.cpp new file mode 100644 index 00000000..747a00a5 --- /dev/null +++ b/libs/base/pxt.cpp @@ -0,0 +1,518 @@ +#include "pxtbase.h" + +using namespace std; + +namespace pxt { + +Action mkAction(int totallen, RefAction *act) { + check(getVTable(act)->classNo == BuiltInType::RefAction, PANIC_INVALID_BINARY_HEADER, 1); +#ifdef PXT_VM + check(act->initialLen <= totallen, PANIC_INVALID_BINARY_HEADER, 13); +#endif + + if (totallen == 0) { + return (TValue)act; // no closure needed + } + + void *ptr = gcAllocate(sizeof(RefAction) + totallen * sizeof(void *)); + RefAction *r = new (ptr) RefAction(); + r->len = totallen; +#ifdef PXT_VM + r->numArgs = act->numArgs; + r->initialLen = act->initialLen; + r->flags = 0; +#endif + r->func = act->func; + memset(r->fields, 0, r->len * sizeof(void *)); + + MEMDBG("mkAction: start=%p => %p", act, r); + + return (Action)r; +} + +RefRecord *mkClassInstance(VTable *vtable) { + intcheck(vtable->methods[0] == &RefRecord_destroy, PANIC_SIZE, 3); + // intcheck(vtable->methods[1] == &RefRecord_print, PANIC_SIZE, 4); + + void *ptr = gcAllocate(vtable->numbytes); + RefRecord *r = new (ptr) RefRecord(vtable); + memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord)); + MEMDBG("mkClass: vt=%p => %p", vtable, r); + return r; +} + +TValue RefRecord::ld(int idx) { + // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 1); + return fields[idx]; +} + +TValue RefRecord::ldref(int idx) { + // DMESG("LD %p len=%d reflen=%d idx=%d", this, len, reflen, idx); + // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 2); + return fields[idx]; +} + +void RefRecord::st(int idx, TValue v) { + // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 3); + fields[idx] = v; +} + +void RefRecord::stref(int idx, TValue v) { + // DMESG("ST %p len=%d reflen=%d idx=%d", this, len, reflen, idx); + // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 4); + fields[idx] = v; +} + +void RefObject::destroyVT() { + ((RefObjectMethod)getVTable(this)->methods[0])(this); +} + +//% +void deleteRefObject(RefObject *obj) { + obj->destroyVT(); +} + +void RefObject::printVT() { + ((RefObjectMethod)getVTable(this)->methods[1])(this); +} + +void RefRecord_destroy(RefRecord *) {} + +void RefRecord_print(RefRecord *r) { + DMESG("RefRecord %p size=%d bytes", r, getVTable(r)->numbytes); +} + +void Segment::set(unsigned i, TValue value) { + if (i < size) { + data[i] = value; + } else if (i < Segment::MaxSize) { + growByMin(i + 1); + data[i] = value; + } else { + return; + } + if (length <= i) { + length = i + 1; + } + +#ifdef DEBUG_BUILD + DMESG("In Segment::set"); + this->print(); +#endif + + return; +} + +static inline int growthFactor(int size) { + if (size == 0) { + return 4; + } + if (size < 64) { + return size * 2; // Double + } + if (size < 512) { + return size * 5 / 3; // Grow by 1.66 rate + } + // Grow by constant rate + if ((unsigned)size + 256 < Segment::MaxSize) + return size + 256; + else + return Segment::MaxSize; +} + +void LLSegment::setLength(unsigned newLen) { + if (newLen > Segment::MaxSize) + return; + + if (newLen > size) { + int newSize = growthFactor(size); + if (newSize < (int)newLen) + newSize = newLen; + + // this will throw if unable to allocate + TValue *tmp = (TValue *)(xmalloc(newSize * sizeof(TValue))); + + // Copy existing data + if (size) { + memcpy(tmp, data, size * sizeof(TValue)); + } + // fill the rest with default value + memset(tmp + size, 0, (newSize - size) * sizeof(TValue)); + + // free older segment; + xfree(data); + + data = tmp; + size = newSize; + } else if (newLen < length) { + memset(data + newLen, 0, (length - newLen) * sizeof(TValue)); + } + + length = newLen; +} + +void LLSegment::set(unsigned idx, TValue v) { + if (idx >= Segment::MaxSize) + return; + if (idx >= length) + setLength(idx + 1); + data[idx] = v; +} + +TValue LLSegment::pop() { + if (length > 0) { + --length; + TValue value = data[length]; + data[length] = 0; + return value; + } + return 0; +} + +void LLSegment::destroy() { + length = size = 0; + xfree(data); + data = nullptr; +} + +void Segment::growByMin(ramint_t minSize) { + ramint_t newSize = max(minSize, (ramint_t)growthFactor(size)); + + if (size < newSize) { + // this will throw if unable to allocate + TValue *tmp = (TValue *)(gcAllocateArray(newSize * sizeof(TValue))); + + // Copy existing data + if (size) + memcpy(tmp, data, size * sizeof(TValue)); + // fill the rest with default value + memset(tmp + size, 0, (newSize - size) * sizeof(TValue)); + + data = tmp; + size = newSize; + +#ifdef DEBUG_BUILD + DMESG("growBy - after reallocation"); + this->print(); +#endif + } + // else { no shrinking yet; } + return; +} + +void Segment::ensure(ramint_t newSize) { + if (newSize < size) { + return; + } + growByMin(newSize); +} + +void Segment::setLength(unsigned newLength) { + if (newLength > size) { + ensure(newLength); + } + length = newLength; + return; +} + +TValue Segment::pop() { +#ifdef DEBUG_BUILD + DMESG("In Segment::pop"); + this->print(); +#endif + + if (length > 0) { + --length; + TValue value = data[length]; + data[length] = Segment::DefaultValue; + return value; + } + return Segment::DefaultValue; +} + +// this function removes an element at index i and shifts the rest of the elements to +// left to fill the gap +TValue Segment::remove(unsigned i) { +#ifdef DEBUG_BUILD + DMESG("In Segment::remove index:%d", i); + this->print(); +#endif + if (i < length) { + // value to return + TValue ret = data[i]; + if (i + 1 < length) { + // Move the rest of the elements to fill in the gap. + memmove(data + i, data + i + 1, (length - i - 1) * sizeof(void *)); + } + length--; + data[length] = Segment::DefaultValue; +#ifdef DEBUG_BUILD + DMESG("After Segment::remove index:%d", i); + this->print(); +#endif + return ret; + } + return Segment::DefaultValue; +} + +// this function inserts element value at index i by shifting the rest of the elements right. +void Segment::insert(unsigned i, TValue value) { +#ifdef DEBUG_BUILD + DMESG("In Segment::insert index:%d value:%d", i, value); + this->print(); +#endif + + if (i < length) { + ensure(length + 1); + + // Move the rest of the elements to fill in the gap. + memmove(data + i + 1, data + i, (length - i) * sizeof(void *)); + + data[i] = value; + length++; + } else { + // This is insert beyond the length, just call set which will adjust the length + set(i, value); + } +#ifdef DEBUG_BUILD + DMESG("After Segment::insert index:%d", i); + this->print(); +#endif +} + +void Segment::print() { + DMESG("Segment: %p, length: %d, size: %d", data, (unsigned)length, (unsigned)size); + for (unsigned i = 0; i < size; i++) { + DMESG("-> %d", (unsigned)(uintptr_t)data[i]); + } +} + +void Segment::destroy() { +#ifdef DEBUG_BUILD + DMESG("In Segment::destroy"); + this->print(); +#endif + length = size = 0; + data = nullptr; +} + +PXT_VTABLE_CTOR(RefCollection) {} + +void RefCollection::destroy(RefCollection *t) { + t->head.destroy(); +} + +void RefCollection::print(RefCollection *t) { + DMESG("RefCollection %p size=%d", t, t->head.getLength()); + t->head.print(); +} + +PXT_VTABLE(RefAction, ValType::Function) +RefAction::RefAction() : PXT_VTABLE_INIT(RefAction) {} + +// fields[] contain captured locals +void RefAction::destroy(RefAction *t) {} + +void RefAction::print(RefAction *t) { +#ifdef PXT_VM + DMESG("RefAction %p pc=%X size=%d", t, (uint32_t)t->func, t->len); +#else + DMESG("RefAction %p pc=%X size=%d", t, (const uint8_t *)t->func - (const uint8_t *)bytecode, + t->len); +#endif +} + +PXT_VTABLE_CTOR(RefRefLocal) { + v = 0; +} + +void RefRefLocal::print(RefRefLocal *t) { + DMESG("RefRefLocal %p v=%p", t, (void *)t->v); +} + +void RefRefLocal::destroy(RefRefLocal *t) { + decr(t->v); +} + +PXT_VTABLE_CTOR(RefMap) {} + +void RefMap::destroy(RefMap *t) { + t->keys.destroy(); + t->values.destroy(); +} + +int RefMap::findIdx(String key) { + auto len = keys.getLength(); + auto data = (String *)keys.getData(); + + // fast path + for (unsigned i = 0; i < len; ++i) { + if (data[i] == key) + return i; + } + + // slow path + auto keylen = key->getUTF8Size(); + auto keydata = key->getUTF8Data(); + for (unsigned i = 0; i < len; ++i) { + auto s = data[i]; + if (s->getUTF8Size() == keylen && memcmp(keydata, s->getUTF8Data(), keylen) == 0) + return i; + } + + return -1; +} + +void RefMap::print(RefMap *t) { + DMESG("RefMap %p size=%d", t, t->keys.getLength()); +} + +void debugMemLeaks() {} + +void error(PXT_PANIC code, int subcode) { + DMESG("Error: %d [%d]", code, subcode); + target_panic(code); +} + +#ifndef PXT_VM +uint16_t *bytecode; +#endif +TValue *globals; + +void checkStr(bool cond, const char *msg) { + if (!cond) { + while (true) { + // uBit.display.scroll(msg, 100); + // uBit.sleep(100); + } + } +} + +#ifdef PXT_VM +int templateHash() { + return (int)vmImg->infoHeader->hexHash; +} + +int programHash() { + return (int)vmImg->infoHeader->programHash; +} + +int getNumGlobals() { + return (int)vmImg->infoHeader->allocGlobals; +} + +String programName() { + return mkString((char *)vmImg->infoHeader->name); +} +#else +int templateHash() { + return ((int *)bytecode)[4]; +} + +int programHash() { + return ((int *)bytecode)[6]; +} + +int getNumGlobals() { + return bytecode[16]; +} + +String programName() { + return ((String *)bytecode)[15]; +} +#endif + +#ifndef PXT_VM +void variantNotSupported(const char *v) { + DMESG("variant not supported: %s", v); + target_panic(PANIC_VARIANT_NOT_SUPPORTED); +} + +void exec_binary(unsigned *pc) { + // XXX re-enable once the calibration code is fixed and [editor/embedded.ts] + // properly prepends a call to [internal_main]. + // ::touch_develop::internal_main(); + + // unique group for radio based on source hash + // ::touch_develop::micro_bit::radioDefaultGroup = programHash(); + + unsigned ver = *pc++; + checkStr(ver == 0x4210, ":( Bad runtime version"); + + bytecode = *((uint16_t **)pc++); // the actual bytecode is here + + if (((uint32_t *)bytecode)[0] == 0x923B8E71) { + variantNotSupported((const char *)bytecode + 16); + return; + } + + globals = (TValue *)app_alloc(sizeof(TValue) * getNumGlobals()); + memset(globals, 0, sizeof(TValue) * getNumGlobals()); + + // can be any valid address, best in RAM for speed + globals[0] = (TValue)&globals; + + // just compare the first word + // TODO + checkStr(((uint32_t *)bytecode)[0] == 0x923B8E70 && (unsigned)templateHash() == *pc, + ":( Failed partial flash"); + + uintptr_t startptr = (uintptr_t)bytecode; + + startptr += 64; // header + + initPerfCounters(); + + initRuntime(); + + runAction0((Action)startptr); + + pxt::releaseFiber(); +} + +void start() { + exec_binary((unsigned *)functionsAndBytecode); +} +#endif + +} // namespace pxt + +namespace Array_ { +//% +bool isArray(TValue arr) { + auto vt = getAnyVTable(arr); + return vt && vt->classNo == BuiltInType::RefCollection; +} +} // namespace Array_ + +namespace pxtrt { +//% expose +RefCollection *keysOf(TValue v) { + auto r = NEW_GC(RefCollection); + MEMDBG("mkColl[keys]: => %p", r); + if (getAnyVTable(v) != &RefMap_vtable) + return r; + auto rm = (RefMap *)v; + auto len = rm->keys.getLength(); + if (!len) + return r; + registerGCObj(r); + r->setLength(len); + auto dst = r->getData(); + memcpy(dst, rm->keys.getData(), len * sizeof(TValue)); + unregisterGCObj(r); + return r; +} +//% expose +TValue mapDeleteByString(RefMap *map, String key) { + if (getAnyVTable((TValue)map) != &RefMap_vtable) + target_panic(PANIC_DELETE_ON_CLASS); + int i = map->findIdx(key); + if (i >= 0) { + map->keys.remove(i); + map->values.remove(i); + } + return TAG_TRUE; +} + +} // namespace pxtrt diff --git a/libs/base/pxt.json b/libs/base/pxt.json old mode 100755 new mode 100644 index 32583edf..5757ad06 --- a/libs/base/pxt.json +++ b/libs/base/pxt.json @@ -1,7 +1,6 @@ { "name": "base", "description": "The base library", - "dependencies": {}, "files": [ "README.md", "pxt-core.d.ts", @@ -22,7 +21,11 @@ "math.ts", "ns.ts", "control.cpp", + "controlgc.cpp", "control.ts", + "interval.ts", + "gcstats.ts", + "poll.ts", "console.ts", "json.ts", "templates.ts", @@ -30,14 +33,16 @@ "pause.ts", "forever.ts", "utfdecoder.ts", - "scheduling.ts" + "scheduling.ts", + "controlmessage.ts", + "perfcounters.ts" ], "testFiles": [ "test.ts" ], "public": true, - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/base", "partial": true, + "dependencies": {}, "yotta": { "optionalConfig": { "PXT_GC_CHECKS": 0 @@ -51,4 +56,4 @@ } ] } -} +} \ No newline at end of file diff --git a/libs/base/pxtbase.h b/libs/base/pxtbase.h new file mode 100644 index 00000000..60883c6e --- /dev/null +++ b/libs/base/pxtbase.h @@ -0,0 +1,1220 @@ +#ifndef __PXTBASE_H +#define __PXTBASE_H + +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Warray-bounds" + +// needed for gcc6; not sure why +#undef min +#undef max + +#define NOLOG(...) \ + do { \ + } while (0) + +#define MEMDBG NOLOG +//#define MEMDBG DMESG +#define MEMDBG2 NOLOG + +#include "pxtconfig.h" +#include "configkeys.h" +#include "TeknikioDevice.h" + +#ifndef PXT_UTF8 +#define PXT_UTF8 0 +#endif + +#if defined(PXT_VM) +#include +#if UINTPTR_MAX == 0xffffffff +#define PXT32 1 +#elif UINTPTR_MAX == 0xffffffffffffffff +#define PXT64 1 +#else +#error "UINTPTR_MAX has invalid value" +#endif +#endif + +#define intcheck(...) check(__VA_ARGS__) +//#define intcheck(...) do {} while (0) + +#ifdef PXT_USE_FLOAT +#define NUMBER float +#else +#define NUMBER double +#endif + +#include +#include +#include + +#ifdef POKY +void *operator new(size_t size, void *ptr); +void *operator new(size_t size); +#else +#include +#endif + +#include "platform.h" +#include "pxtcore.h" + +#ifndef PXT_REGISTER_RESET +#define PXT_REGISTER_RESET(fn) ((void)0) +#endif + +#define PXT_REFCNT_FLASH 0xfffe + +#define CONCAT_1(a, b) a##b +#define CONCAT_0(a, b) CONCAT_1(a, b) +// already provided in some platforms, like mbedos +#ifndef STATIC_ASSERT +#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }; +#endif + +#ifndef ramint_t +// this type limits size of arrays +#if defined(__linux__) || defined(PXT_VM) +// TODO fix the inline array accesses to take note of this! +#define ramint_t uint32_t +#else +#define ramint_t uint16_t +#endif +#endif + +#ifndef PXT_IN_ISR +#define PXT_IN_ISR() (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) +#endif + +#ifdef POKY +inline void *operator new(size_t, void *p) { + return p; +} +inline void *operator new[](size_t, void *p) { + return p; +} +#endif + +namespace pxt { + +void initTeknikio(); + +}; + +namespace pxt { + +template inline const T &max(const T &a, const T &b) { + if (a < b) + return b; + return a; +} + +template inline const T &min(const T &a, const T &b) { + if (a < b) + return a; + return b; +} + +template inline void swap(T &a, T &b) { + T tmp = a; + a = b; + b = tmp; +} + +// +// Tagged values (assume 4 bytes for now, Cortex-M0) +// +struct TValueStruct {}; +typedef TValueStruct *TValue; + +typedef TValue TNumber; +typedef TValue Action; +typedef TValue ImageLiteral; + +// To be implemented by the target +extern "C" void target_panic(int error_code); +extern "C" void target_reset(); +void sleep_ms(unsigned ms); +void sleep_us(uint64_t us); +void releaseFiber(); +uint64_t current_time_us(); +int current_time_ms(); +void initRuntime(); +void initSystemTimer(); +void sendSerial(const char *data, int len); +void setSendToUART(void (*f)(const char *, int)); +uint64_t getLongSerialNumber(); +void registerWithDal(int id, int event, Action a, int flags = 16); // EVENT_LISTENER_DEFAULT_FLAGS +void runInParallel(Action a); +void runForever(Action a); +void waitForEvent(int id, int event); +//% +unsigned afterProgramPage(); +//% +void dumpDmesg(); +uint32_t hash_fnv1(const void *data, unsigned len); + +// also defined DMESG macro +// end + +#define TAGGED_SPECIAL(n) (TValue)(void *)((n << 2) | 2) +#define TAG_FALSE TAGGED_SPECIAL(2) // 10 +#define TAG_TRUE TAGGED_SPECIAL(16) // 66 +#define TAG_UNDEFINED (TValue)0 +#define TAG_NULL TAGGED_SPECIAL(1) // 6 +#define TAG_NAN TAGGED_SPECIAL(3) // 14 +#define TAG_NUMBER(n) (TNumber)(void *)(((uintptr_t)(uint32_t)(n) << 1) | 1) +#define TAG_NON_VALUE TAGGED_SPECIAL(4) // 18; doesn't represent any JS value + +#ifdef PXT_VM +inline bool isEncodedDouble(uint64_t v) { + return (v >> 48) != 0; +} +#endif + +inline bool isDouble(TValue v) { +#ifdef PXT64 + return ((uintptr_t)v >> 48) != 0; +#else + (void)v; + return false; +#endif +} + +inline bool isPointer(TValue v) { + return !isDouble(v) && v != 0 && ((intptr_t)v & 3) == 0; +} + +inline bool isTagged(TValue v) { + return (!isDouble(v) && ((intptr_t)v & 3)) || !v; +} + +inline bool isInt(TValue v) { + return !isDouble(v) && ((intptr_t)v & 1); +} + +inline bool isSpecial(TValue v) { + return !isDouble(v) && ((intptr_t)v & 2); +} + +inline bool bothNumbers(TValue a, TValue b) { + return !isDouble(a) && !isDouble(b) && ((intptr_t)a & (intptr_t)b & 1); +} + +inline int numValue(TValue n) { + return (int)((intptr_t)n >> 1); +} + +inline bool canBeTagged(int v) { + (void)v; +#ifdef PXT_BOX_DEBUG + return false; +#elif defined(PXT64) + return true; +#else + return (v << 1) >> 1 == v; +#endif +} + +// see https://anniecherkaev.com/the-secret-life-of-nan + +#define NanBoxingOffset 0x1000000000000LL + +template TO bitwise_cast(FROM in) { + STATIC_ASSERT(sizeof(TO) == sizeof(FROM)); + union { + FROM from; + TO to; + } u; + u.from = in; + return u.to; +} + +inline double decodeDouble(uint64_t v) { + return bitwise_cast(v - NanBoxingOffset); +} + +#ifdef PXT64 +STATIC_ASSERT(sizeof(void *) == 8); +inline double doubleVal(TValue v) { + return bitwise_cast((uint64_t)v - NanBoxingOffset); +} + +inline TValue tvalueFromDouble(double d) { + return (TValue)(bitwise_cast(d) + NanBoxingOffset); +} +#else +STATIC_ASSERT(sizeof(void *) == 4); +#endif + +// keep in sym with sim/control.ts +typedef enum { + PANIC_CODAL_OOM = 20, + PANIC_GC_OOM = 21, + PANIC_GC_TOO_BIG_ALLOCATION = 22, + PANIC_CODAL_HEAP_ERROR = 30, + PANIC_CODAL_NULL_DEREFERENCE = 40, + PANIC_CODAL_USB_ERROR = 50, + PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR = 90, + + PANIC_INVALID_BINARY_HEADER = 901, + PANIC_OUT_OF_BOUNDS = 902, + PANIC_REF_DELETED = 903, + PANIC_SIZE = 904, + PANIC_INVALID_VTABLE = 905, + PANIC_INTERNAL_ERROR = 906, + PANIC_NO_SUCH_CONFIG = 907, + PANIC_NO_SUCH_PIN = 908, + PANIC_INVALID_ARGUMENT = 909, + PANIC_MEMORY_LIMIT_EXCEEDED = 910, + PANIC_SCREEN_ERROR = 911, + PANIC_MISSING_PROPERTY = 912, + PANIC_INVALID_IMAGE = 913, + PANIC_CALLED_FROM_ISR = 914, + PANIC_HEAP_DUMPED = 915, + PANIC_STACK_OVERFLOW = 916, + PANIC_BLOCKING_TO_STRING = 917, + PANIC_VM_ERROR = 918, + PANIC_SETTINGS_CLEARED = 920, + PANIC_SETTINGS_OVERLOAD = 921, + PANIC_SETTINGS_SECRET_MISSING = 922, + PANIC_DELETE_ON_CLASS = 923, + PANIC_OUT_OF_TIMERS = 924, + PANIC_JACDAC = 925, + PANIC_MICROPHONE_MISSING = 926, + PANIC_VARIANT_NOT_SUPPORTED = 927, + + PANIC_CAST_FIRST = 980, + PANIC_CAST_FROM_UNDEFINED = 980, + PANIC_CAST_FROM_BOOLEAN = 981, + PANIC_CAST_FROM_NUMBER = 982, + PANIC_CAST_FROM_STRING = 983, + PANIC_CAST_FROM_OBJECT = 984, + PANIC_CAST_FROM_FUNCTION = 985, + PANIC_CAST_FROM_NULL = 989, + + PANIC_UNHANDLED_EXCEPTION = 999, + +} PXT_PANIC; + +extern const uintptr_t functionsAndBytecode[]; +extern TValue *globals; +extern uint16_t *bytecode; +class RefRecord; + +// Utility functions + +typedef TValue (*RunActionType)(Action a, TValue arg0, TValue arg1, TValue arg2); + +#define asmRunAction3 ((RunActionType)(((uintptr_t *)bytecode)[12])) + +static inline TValue runAction3(Action a, TValue arg0, TValue arg1, TValue arg2) { + return asmRunAction3(a, arg0, arg1, 0); +} +static inline TValue runAction2(Action a, TValue arg0, TValue arg1) { + return asmRunAction3(a, arg0, arg1, 0); +} +static inline TValue runAction1(Action a, TValue arg0) { + return asmRunAction3(a, arg0, 0, 0); +} +static inline TValue runAction0(Action a) { + return asmRunAction3(a, 0, 0, 0); +} + +class RefAction; +class BoxedString; +struct VTable; + +//% +Action mkAction(int totallen, RefAction *act); +//% expose +int templateHash(); +//% expose +int programHash(); +//% expose +BoxedString *programName(); +//% expose +unsigned programSize(); +//% +int getNumGlobals(); +//% +RefRecord *mkClassInstance(VTable *vt); +//% +void debugMemLeaks(); +//% +void anyPrint(TValue v); + +//% +int getConfig(int key, int defl = -1); + +//% +int toInt(TNumber v); +//% +unsigned toUInt(TNumber v); +//% +NUMBER toDouble(TNumber v); +//% +float toFloat(TNumber v); +//% +TNumber fromDouble(NUMBER r); +//% +TNumber fromFloat(float r); + +//% +TNumber fromInt(int v); +//% +TNumber fromUInt(unsigned v); +//% +TValue fromBool(bool v); +//% +bool eq_bool(TValue a, TValue b); +//% +bool eqq_bool(TValue a, TValue b); + +//% +void failedCast(TValue v, void *addr = NULL); +//% +void missingProperty(TValue v); + +void error(PXT_PANIC code, int subcode = 0); +void exec_binary(unsigned *pc); +void start(); + +struct HandlerBinding { + HandlerBinding *next; + int source; + int value; + Action action; +}; +HandlerBinding *findBinding(int source, int value); +HandlerBinding *nextBinding(HandlerBinding *curr, int source, int value); +void setBinding(int source, int value, Action act); + +// Legacy stuff; should no longer be used +//% +TValue incr(TValue e); +//% +void decr(TValue e); + +inline TValue incr(TValue e) { + return e; +} +inline void decr(TValue e) {} + +class RefObject; + +static inline RefObject *incrRC(RefObject *r) { + return r; +} +static inline void decrRC(RefObject *) {} + +inline void *ptrOfLiteral(int offset) { + return &bytecode[offset]; +} + +// Checks if object is ref-counted, and has a custom PXT vtable in front +// TODO +inline bool isRefCounted(TValue e) { + return isPointer(e); +} + +inline void check(int cond, PXT_PANIC code, int subcode = 0) { + if (!cond) + error(code, subcode); +} + +inline void oops(int subcode = 0) { + target_panic(800 + subcode); +} + +class RefObject; + +typedef void (*RefObjectMethod)(RefObject *self); +typedef unsigned (*RefObjectSizeMethod)(RefObject *self); +typedef void *PVoid; +typedef void **PPVoid; + +typedef void *Object_; + +#define VTABLE_MAGIC 0xF9 + +enum class ValType : uint8_t { + Undefined, + Boolean, + Number, + String, + Object, + Function, +}; + +// keep in sync with pxt-core (search for the type name) +enum class BuiltInType : uint16_t { + BoxedString = 1, + BoxedNumber = 2, + BoxedBuffer = 3, + RefAction = 4, + RefImage = 5, + RefCollection = 6, + RefRefLocal = 7, + RefMap = 8, + RefMImage = 9, // microbit-specific + MMap = 10, // linux, mostly ev3 + BoxedString_SkipList = 11, // used by VM bytecode representation only + BoxedString_ASCII = 12, // ditto + User0 = 16, +}; + +struct VTable { + uint16_t numbytes; + ValType objectType; + uint8_t magic; +#ifdef PXT_VM + uint16_t ifaceHashEntries; + BuiltInType lastClassNo; +#else + PVoid *ifaceTable; +#endif + BuiltInType classNo; + uint16_t reserved; + uint32_t ifaceHashMult; + + // we only use the first few methods here; pxt will generate more + PVoid methods[8]; +}; + +//% +extern const VTable string_inline_ascii_vt; +#if PXT_UTF8 +//% +extern const VTable string_inline_utf8_vt; +//% +extern const VTable string_cons_vt; +//% +extern const VTable string_skiplist16_vt; +//% +extern const VTable string_skiplist16_packed_vt; +#endif +//% +extern const VTable buffer_vt; +//% +extern const VTable number_vt; +//% +extern const VTable RefAction_vtable; + +#ifndef PXT_IS_READONLY +// assume ARM - ram addresses are 0x2000_0000+; flash is either 0x0+ or 0x0800_0000+ +#define PXT_IS_READONLY(v) (isTagged(v) || !((uintptr_t)v >> 28)) +#endif + +inline bool isReadOnly(TValue v) { + return PXT_IS_READONLY(v); +} + +// A base abstract class for ref-counted objects. +class RefObject { + public: + const VTable *vtable; + + RefObject(const VTable *vt) { +#if defined(PXT32) && defined(PXT_VM) && !defined(PXT_ESP32) + if ((uint32_t)vt & 0xf0000000) + target_panic(PANIC_INVALID_VTABLE); +#endif + vtable = vt; + } + + void destroyVT(); + void printVT(); + + inline uintptr_t vt() { return (uintptr_t)vtable; } + inline void setVT(uintptr_t v) { vtable = (const VTable *)v; } + + inline void ref() {} + inline void unref() {} + inline bool isReadOnly() { return pxt::isReadOnly((TValue)this); } +}; + +class Segment { + private: + TValue *data; + ramint_t length; + ramint_t size; + + // this just gives max value of ramint_t + void growByMin(ramint_t minSize); + void ensure(ramint_t newSize); + + public: + static constexpr ramint_t MaxSize = (((1U << (8 * sizeof(ramint_t) - 1)) - 1) << 1) + 1; + static constexpr TValue DefaultValue = TAG_UNDEFINED; // == NULL + + Segment() : data(nullptr), length(0), size(0) {} + + TValue get(unsigned i) { return i < length ? data[i] : NULL; } + void set(unsigned i, TValue value); + + unsigned getLength() { return length; }; + void setLength(unsigned newLength); + + void push(TValue value) { set(length, value); } + TValue pop(); + + TValue remove(unsigned i); + void insert(unsigned i, TValue value); + + void destroy(); + + void print(); + + TValue *getData() { return data; } +}; + +// Low-Level segment using system malloc +class LLSegment { + private: + TValue *data; + ramint_t length; + ramint_t size; + + public: + LLSegment() : data(nullptr), length(0), size(0) {} + + void set(unsigned idx, TValue v); + void push(TValue value) { set(length, value); } + TValue pop(); + void destroy(); + void setLength(unsigned newLen); + + TValue get(unsigned i) { return i < length ? data[i] : NULL; } + unsigned getLength() { return length; }; + TValue *getData() { return data; } +}; + +// A ref-counted collection of either primitive or ref-counted objects (String, Image, +// user-defined record, another collection) +class RefCollection : public RefObject { + public: + Segment head; + + RefCollection(); + + static void destroy(RefCollection *coll); + static void scan(RefCollection *coll); + static unsigned gcsize(RefCollection *coll); + static void print(RefCollection *coll); + + unsigned length() { return head.getLength(); } + void setLength(unsigned newLength) { head.setLength(newLength); } + TValue getAt(int i) { return head.get(i); } + TValue *getData() { return head.getData(); } +}; + +class RefMap : public RefObject { + public: + Segment keys; + Segment values; + + RefMap(); + static void destroy(RefMap *map); + static void scan(RefMap *map); + static unsigned gcsize(RefMap *coll); + static void print(RefMap *map); + int findIdx(BoxedString *key); +}; + +// A ref-counted, user-defined JS object. +class RefRecord : public RefObject { + public: + // The object is allocated, so that there is space at the end for the fields. + TValue fields[]; + + RefRecord(VTable *v) : RefObject(v) {} + + TValue ld(int idx); + TValue ldref(int idx); + void st(int idx, TValue v); + void stref(int idx, TValue v); +}; + +static inline VTable *getVTable(RefObject *r) { + return (VTable *)(r->vt() & ~1); +} + +static inline VTable *getAnyVTable(TValue v) { + if (!isRefCounted(v)) + return NULL; + auto vt = getVTable((RefObject *)v); + if (vt->magic == VTABLE_MAGIC) + return vt; + return NULL; +} + +// these are needed when constructing vtables for user-defined classes +//% +void RefRecord_destroy(RefRecord *r); +//% +void RefRecord_print(RefRecord *r); +//% +void RefRecord_scan(RefRecord *r); +//% +unsigned RefRecord_gcsize(RefRecord *r); + +typedef TValue (*ActionCB)(TValue *captured, TValue arg0, TValue arg1, TValue arg2); + +// Ref-counted function pointer. +class RefAction : public RefObject { + public: + uint16_t len; + uint16_t numArgs; +#ifdef PXT_VM + uint16_t initialLen; + uint16_t flags; + uintptr_t func; +#else + ActionCB func; // The function pointer +#endif + // fields[] contain captured locals + TValue fields[]; + + static void destroy(RefAction *act); + static void scan(RefAction *act); + static unsigned gcsize(RefAction *coll); + static void print(RefAction *act); + + RefAction(); + + inline void stCore(int idx, TValue v) { + // DMESG("ST [%d] = %d ", idx, v); this->print(); + intcheck(0 <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 10); + intcheck(fields[idx] == 0, PANIC_OUT_OF_BOUNDS, 11); // only one assignment permitted + fields[idx] = v; + } +}; + +// These two are used to represent locals written from inside inline functions +class RefRefLocal : public RefObject { + public: + TValue v; + static void destroy(RefRefLocal *l); + static void scan(RefRefLocal *l); + static unsigned gcsize(RefRefLocal *l); + static void print(RefRefLocal *l); + RefRefLocal(); +}; + +typedef int color; + +// note: this is hardcoded in PXT (hexfile.ts) + +class BoxedNumber : public RefObject { + public: + NUMBER num; + BoxedNumber() : RefObject(&number_vt) {} +} __attribute__((packed)); + +class BoxedString : public RefObject { + public: + union { + struct { + uint16_t length; // ==size + char data[0]; + } ascii; +#if PXT_UTF8 + struct { + uint16_t size; + char data[0]; + } utf8; + struct { + BoxedString *left; + BoxedString *right; + } cons; + struct { + uint16_t size; // in bytes + uint16_t length; // in characters + uint16_t *list; + } skip; + struct { + uint16_t size; // in bytes + uint16_t length; // in characters + uint16_t list[0]; + } skip_pack; +#endif + }; + +#if PXT_UTF8 + uintptr_t runMethod(int idx) { + return ((uintptr_t(*)(BoxedString *))vtable->methods[idx])(this); + } + const char *getUTF8Data() { return (const char *)runMethod(4); } + uint32_t getUTF8Size() { return (uint32_t)runMethod(5); } + // in characters + uint32_t getLength() { return (uint32_t)runMethod(6); } + const char *getUTF8DataAt(uint32_t pos) { + auto meth = + ((const char *(*)(BoxedString *, uint32_t))vtable->methods[7]); + return meth(this, pos); + } +#else + const char *getUTF8Data() { return ascii.data; } + uint32_t getUTF8Size() { return ascii.length; } + uint32_t getLength() { return ascii.length; } + const char *getUTF8DataAt(uint32_t pos) { return pos < ascii.length ? ascii.data + pos : NULL; } +#endif + + TNumber charCodeAt(int pos); + + BoxedString(const VTable *vt) : RefObject(vt) {} +}; + +// cross version compatible way of accessing string data +#ifndef PXT_STRING_DATA +#define PXT_STRING_DATA(str) str->getUTF8Data() +#endif + +// cross version compatible way of accessing string length +#ifndef PXT_STRING_DATA_LENGTH +#define PXT_STRING_DATA_LENGTH(str) str->getUTF8Size() +#endif + +class BoxedBuffer : public RefObject { + public: + // data needs to be word-aligned, so we use 32 bits for length + int length; + uint8_t data[0]; + BoxedBuffer() : RefObject(&buffer_vt) {} +}; + +// cross version compatible way of access data field +#ifndef PXT_BUFFER_DATA +#define PXT_BUFFER_DATA(buffer) buffer->data +#endif + +// cross version compatible way of access data length +#ifndef PXT_BUFFER_LENGTH +#define PXT_BUFFER_LENGTH(buffer) buffer->length +#endif + +#ifndef PXT_CREATE_BUFFER +#define PXT_CREATE_BUFFER(data, len) pxt::mkBuffer(data, len) +#endif + +// Legacy format: +// the first byte of data indicates the format - currently 0xE1 or 0xE4 to 1 or 4 bit bitmaps +// second byte indicates width in pixels +// third byte indicates the height (which should also match the size of the buffer) +// just like ordinary buffers, these can be layed out in flash + +// Current format: +// 87 BB WW WW HH HH 00 00 DATA +// that is: 0x87, 0x01 or 0x04 - bpp, width in little endian, height, 0x00, 0x00 followed by data +// for 4 bpp images, rows are word-aligned (as in legacy) + +#define IMAGE_HEADER_MAGIC 0x87 + +struct ImageHeader { + uint8_t magic; + uint8_t bpp; + uint16_t width; + uint16_t height; + uint16_t padding; + uint8_t pixels[0]; +}; + +class RefImage : public RefObject { + public: + BoxedBuffer *buffer; + + RefImage(BoxedBuffer *buf); + RefImage(uint32_t sz); + + void setBuffer(BoxedBuffer *b); + + uint8_t *data() { return buffer->data; } + int length() { return (int)buffer->length; } + + ImageHeader *header() { return (ImageHeader *)buffer->data; } + int pixLength() { return length() - sizeof(ImageHeader); } + + int width() { return header()->width; } + int height() { return header()->height; } + int wordHeight(); + int bpp() { return header()->bpp; } + + bool hasPadding() { return (height() & 0x7) != 0; } + + uint8_t *pix() { return header()->pixels; } + + int byteHeight() { + if (bpp() == 1) + return (height() + 7) >> 3; + else if (bpp() == 4) + return ((height() * 4 + 31) >> 5) << 2; + else { + oops(21); + return -1; + } + } + + uint8_t *pix(int x, int y) { + uint8_t *d = &pix()[byteHeight() * x]; + if (y) { + if (bpp() == 1) + d += y >> 3; + else if (bpp() == 4) + d += y >> 1; + } + return d; + } + + uint8_t fillMask(color c); + bool inRange(int x, int y); + void clamp(int *x, int *y); + void makeWritable(); + + static void destroy(RefImage *t); + static void scan(RefImage *t); + static unsigned gcsize(RefImage *t); + static void print(RefImage *t); +}; + +RefImage *mkImage(int w, int h, int bpp); + +typedef BoxedBuffer *Buffer; +typedef BoxedString *String; +typedef RefImage *Image_; + +uint32_t toRealUTF8(String str, uint8_t *dst); + +// keep in sync with github/pxt/pxtsim/libgeneric.ts +enum class NumberFormat { + Int8LE = 1, + UInt8LE, + Int16LE, + UInt16LE, + Int32LE, + Int8BE, + UInt8BE, + Int16BE, + UInt16BE, + Int32BE, + + UInt32LE, + UInt32BE, + Float32LE, + Float64LE, + Float32BE, + Float64BE, +}; + +// this will, unlike mkStringCore, UTF8-canonicalize the data +String mkString(const char *data, int len = -1); +// data can be NULL in both cases +Buffer mkBuffer(const void *data, int len); +String mkStringCore(const char *data, int len = -1); + +TNumber getNumberCore(uint8_t *buf, int size, NumberFormat format); +void setNumberCore(uint8_t *buf, int size, NumberFormat format, TNumber value); + +void seedRandom(unsigned seed); +void seedAddRandom(unsigned seed); +// max is inclusive +unsigned getRandom(unsigned max); + +ValType valType(TValue v); + +// this is equivalent to JS `throw v`; it will leave +// the current function(s), all the way until the nearest try block and +// ignore all destructors (think longjmp()) +void throwValue(TValue v); + +void registerGC(TValue *root, int numwords = 1); +void unregisterGC(TValue *root, int numwords = 1); +void registerGCPtr(TValue ptr); +void unregisterGCPtr(TValue ptr); +static inline void registerGCObj(RefObject *ptr) { + registerGCPtr((TValue)ptr); +} +static inline void unregisterGCObj(RefObject *ptr) { + unregisterGCPtr((TValue)ptr); +} +void gc(int flags); + +struct StackSegment { + void *top; + void *bottom; + StackSegment *next; +}; + +#define NUM_TRY_FRAME_REGS 3 +struct TryFrame { + TryFrame *parent; + uintptr_t registers[NUM_TRY_FRAME_REGS]; +}; + +struct ThreadContext { + TValue *globals; + StackSegment stack; + TryFrame *tryFrame; + TValue thrownValue; +#ifdef PXT_GC_THREAD_LIST + ThreadContext *next; + ThreadContext *prev; +#endif +}; + +#ifdef PXT_GC_THREAD_LIST +extern ThreadContext *threadContexts; +void *threadAddressFor(ThreadContext *, void *sp); +#endif + +void releaseThreadContext(ThreadContext *ctx); +ThreadContext *getThreadContext(); +void setThreadContext(ThreadContext *ctx); + +#ifndef PXT_GC_THREAD_LIST +void gcProcessStacks(int flags); +#endif + +void gcProcess(TValue v); +void gcFreeze(); + +#ifdef PXT_VM +void gcStartup(); +void gcPreStartup(); +#endif + +void coreReset(); +void gcReset(); +void systemReset(); + +void *gcAllocate(int numbytes); +void *gcAllocateArray(int numbytes); +extern "C" void *app_alloc(int numbytes); +extern "C" void *app_free(void *ptr); +extern "C" void *app_alloc_at(void *at, int numbytes); +void gcPreAllocateBlock(uint32_t sz); + +int redirectSamples(int16_t *dst, int numsamples, int samplerate); + +#ifdef PXT64 +#define TOWORDS(bytes) (((bytes) + 7) >> 3) +#else +#define TOWORDS(bytes) (((bytes) + 3) >> 2) +#endif + +#ifndef PXT_VM +#define soft_panic target_panic +#endif + +extern int debugFlags; + +enum class PerfCounters { + GC, +}; + +#ifdef PXT_PROFILE +#ifndef PERF_NOW +#error "missing platform timer support" +#endif + +struct PerfCounter { + uint32_t value; + uint32_t numstops; + uint32_t start; +}; + +extern struct PerfCounter *perfCounters; + +void initPerfCounters(); +//% +void dumpPerfCounters(); +//% +void startPerfCounter(PerfCounters n); +//% +void stopPerfCounter(PerfCounters n); +#else +inline void startPerfCounter(PerfCounters n) {} +inline void stopPerfCounter(PerfCounters n) {} +inline void initPerfCounters() {} +inline void dumpPerfCounters() {} +#endif + +// Handling of built-in string literals (like "[Object]", "true" etc.). + +// This has the same layout as BoxedString, but has statically allocated buffer +template struct BoxedStringLayout { + const void *vtable; + uint16_t size; + const char data[N]; +}; + +template constexpr size_t _boxedStringLen(char const (&)[N]) { + return N; +} + +// strings defined here as used as (String)name +#define PXT_DEF_STRING(name, val) \ + const BoxedStringLayout<_boxedStringLen(val)> name[1] = { \ + {&pxt::string_inline_ascii_vt, _boxedStringLen(val) - 1, val}}; + +// bigger value - less memory, but slower +// 16/20 keeps s.length and s.charCodeAt(i) at about 200 cycles (for actual unicode strings), +// which is similar to amortized allocation time +#define PXT_STRING_SKIP_INCR 16 // needs to be power of 2; needs to be kept in sync with compiler +#define PXT_STRING_MIN_SKIP 20 // min. size of string to use skip list; static code has its own limit + +#define PXT_NUM_SKIP_ENTRIES(p) ((p)->skip.length / PXT_STRING_SKIP_INCR) +#define PXT_SKIP_DATA_IND(p) ((const char *)(p->skip.list + PXT_NUM_SKIP_ENTRIES(p))) +#define PXT_SKIP_DATA_PACK(p) ((const char *)(p->skip_pack.list + PXT_NUM_SKIP_ENTRIES(p))) + +} // namespace pxt + +using namespace pxt; + +namespace numops { +//% +String toString(TValue v); +//% +int toBool(TValue v); +//% +int toBoolDecr(TValue v); +} // namespace numops + +namespace pxt { +inline bool toBoolQuick(TValue v) { + if (v == TAG_TRUE) + return true; + if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NULL) + return false; + return numops::toBool(v); +} +} // namespace pxt + +namespace pxtrt { +//% +RefMap *mkMap(); +//% +TValue mapGetByString(RefMap *map, String key); +//% +int lookupMapKey(String key); +//% +TValue mapGet(RefMap *map, unsigned key); +//% expose +void mapSetByString(RefMap *map, String key, TValue val); +//% +void mapSet(RefMap *map, unsigned key, TValue val); +} // namespace pxtrt + +namespace pins { +Buffer createBuffer(int size); +} + +namespace String_ { +//% +int compare(String a, String b); +} // namespace String_ + +namespace Array_ { +//% +RefCollection *mk(); +//% +int length(RefCollection *c); +//% +void setLength(RefCollection *c, int newLength); +//% +void push(RefCollection *c, TValue x); +//% +TValue pop(RefCollection *c); +//% +TValue getAt(RefCollection *c, int x); +//% +void setAt(RefCollection *c, int x, TValue y); +//% +TValue removeAt(RefCollection *c, int x); +//% +void insertAt(RefCollection *c, int x, TValue value); +//% +int indexOf(RefCollection *c, TValue x, int start); +//% +bool removeElement(RefCollection *c, TValue x); +} // namespace Array_ + +#define NEW_GC(T, ...) new (gcAllocate(sizeof(T))) T(__VA_ARGS__) + +// The ARM Thumb generator in the JavaScript code is parsing +// the hex file and looks for the magic numbers as present here. +// +// Then it fetches function pointer addresses from there. +// +// The vtable pointers are there, so that the ::emptyData for various types +// can be patched with the right vtable. +// +#define PXT_SHIMS_BEGIN \ + namespace pxt { \ + const uintptr_t functionsAndBytecode[] \ + __attribute__((aligned(0x20))) = {0x08010801, 0x42424242, 0x08010801, 0x8de9d83e, + +#define PXT_SHIMS_END \ + } \ + ; \ + } + +#if !defined(X86_64) && !defined(PXT_VM) +#pragma GCC diagnostic ignored "-Wpmf-conversions" +#endif + +#ifdef PXT_VM +#define DEF_VTABLE(name, tp, valtype, ...) \ + const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp, BuiltInType::tp, \ + 0, 0, {__VA_ARGS__}}; +#else +#define DEF_VTABLE(name, tp, valtype, ...) \ + const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp, \ + 0, 0, {__VA_ARGS__}}; +#endif + +#define PXT_VTABLE(classname, valtp) \ + DEF_VTABLE(classname##_vtable, classname, valtp, (void *)&classname::destroy, \ + (void *)&classname::print, (void *)&classname::scan, (void *)&classname::gcsize) + +#define PXT_VTABLE_INIT(classname) RefObject(&classname##_vtable) + +#define PXT_VTABLE_CTOR(classname) \ + PXT_VTABLE(classname, ValType::Object) \ + classname::classname() : PXT_VTABLE_INIT(classname) + +#define PXT_MAIN \ + int main() { \ + pxt::initTeknikio(); \ + pxt::start(); \ + return 0; \ + } + +#define PXT_FNPTR(x) (uintptr_t)(void *)(x) + +#define PXT_ABI(...) + +#define JOIN(a, b) a##b +/// Defines getClassName() function to fetch the singleton +#define SINGLETON(ClassName) \ + static ClassName *JOIN(inst, ClassName); \ + ClassName *JOIN(get, ClassName)() { \ + if (!JOIN(inst, ClassName)) \ + JOIN(inst, ClassName) = new ClassName(); \ + return JOIN(inst, ClassName); \ + } + +/// Defines getClassName() function to fetch the singleton if PIN present +#define SINGLETON_IF_PIN(ClassName, pin) \ + static ClassName *JOIN(inst, ClassName); \ + ClassName *JOIN(get, ClassName)() { \ + if (!JOIN(inst, ClassName) && LOOKUP_PIN(pin)) \ + JOIN(inst, ClassName) = new ClassName(); \ + return JOIN(inst, ClassName); \ + } + +#ifdef PXT_VM +#include "vm.h" +#endif + +#endif diff --git a/libs/base/scheduling.ts b/libs/base/scheduling.ts new file mode 100644 index 00000000..93bc1af6 --- /dev/null +++ b/libs/base/scheduling.ts @@ -0,0 +1,56 @@ +/** + * Calls a function with a fixed time delay between each call to that function. + * @param func + * @param delay + */ +//% +function setInterval(func: () => void, delay: number): number { + delay = Math.max(10, delay | 0); + return control.setInterval(func, delay, control.IntervalMode.Interval); +} + +/** + * Cancels repeated action which was set up using setInterval(). + * @param intervalId + */ +//% +function clearInterval(intervalId: number) { + control.clearInterval(intervalId, control.IntervalMode.Interval); +} + +/** + * Calls a function after specified delay. + * @param func + * @param delay + */ +//% +function setTimeout(func: () => void, delay: number): number { + return control.setInterval(func, delay, control.IntervalMode.Timeout); +} + +/** + * Clears the delay set by setTimeout(). + * @param intervalId + */ +//% +function clearTimeout(intervalId: number) { + control.clearInterval(intervalId, control.IntervalMode.Timeout); +} + +/** + * Calls a function as soon as possible. + * @param func + */ +//% +function setImmediate(func: () => void): number { + return control.setInterval(func, 0, control.IntervalMode.Immediate); +} + +/** + * Cancels the immediate actions. + * @param intervalId + */ +//% +function clearImmediate(intervalId: number) { + control.clearInterval(intervalId, control.IntervalMode.Immediate); +} diff --git a/libs/base/shims.d.ts b/libs/base/shims.d.ts old mode 100755 new mode 100644 index d54c32f0..6cc66c9e --- a/libs/base/shims.d.ts +++ b/libs/base/shims.d.ts @@ -87,6 +87,12 @@ declare interface Buffer { */ //% shim=BufferMethods::write write(dstOffset: int32, src: Buffer): void; + + /** + * Compute k-bit FNV-1 non-cryptographic hash of the buffer. + */ + //% shim=BufferMethods::hash + hash(bits: int32): uint32; } declare namespace control { @@ -94,14 +100,14 @@ declare namespace control { * Create a new zero-initialized buffer. * @param size number of bytes in the buffer */ - //% shim=control::createBuffer + //% deprecated=1 shim=control::createBuffer function createBuffer(size: int32): Buffer; /** * Create a new buffer with UTF8-encoded string * @param str the string to put in the buffer */ - //% shim=control::createBufferFromUTF8 + //% deprecated=1 shim=control::createBufferFromUTF8 function createBufferFromUTF8(str: string): Buffer; } declare namespace loops { diff --git a/libs/base/sim/cfg.ts b/libs/base/sim/cfg.ts new file mode 100644 index 00000000..5c183d65 --- /dev/null +++ b/libs/base/sim/cfg.ts @@ -0,0 +1,20 @@ +namespace pxsim { + export interface EdgeConnectorBoard { + edgeConnectorState: EdgeConnectorState; + } +} + +namespace pxsim.pxtcore { + export function getPin(id: number): pxsim.Pin { + const b = board() as EdgeConnectorBoard; + if (b && b.edgeConnectorState) + return b.edgeConnectorState.getPin(id); + return undefined; + } + export function lookupPinCfg(key: number): pxsim.Pin { + return getPinCfg(key); + } + export function getPinCfg(key: number): pxsim.Pin { + return getPin(getConfig(key, -1)) + } +} diff --git a/libs/base/sim/control.ts b/libs/base/sim/control.ts new file mode 100644 index 00000000..2203026e --- /dev/null +++ b/libs/base/sim/control.ts @@ -0,0 +1,220 @@ +namespace pxsim.pxtcore { + // TODO: add in support for mode, as in CODAL + export function registerWithDal(id: number, evid: number, handler: RefAction, mode: number = 0) { + board().bus.listen(id, evid, handler); + } + + export function deepSleep() { + // TODO? + console.log("deep sleep requested") + } +} + +namespace pxsim.BufferMethods { + function fnv1(data: Uint8Array) { + let h = 0x811c9dc5 + for (let i = 0; i < data.length; ++i) { + h = (Math as any).imul(h, 0x1000193) ^ data[i] + } + return h + } + + export function hash(buf: RefBuffer, bits: number) { + bits |= 0 + if (bits < 1) + return 0 + const h = fnv1(buf.data) + if (bits >= 32) + return h >>> 0 + else + return ((h ^ (h >>> bits)) & ((1 << bits) - 1)) >>> 0 + } +} + +namespace pxsim.control { + export let runInParallel = thread.runInBackground; + export let delay = thread.pause; + + export function reset() { + pxsim.Runtime.postMessage({ + type: "simulator", + command: "restart", + controlReset: true + }) + const cb = getResume(); + } + export function waitMicros(micros: number) { + thread.pause(micros / 1000); // it prempts not much we can do here. + } + export function deviceName(): string { + let b = board(); + return b && b.id + ? b.id.slice(0, 4) + : "abcd"; + } + export function _ramSize() { + return 32 * 1024 * 1024; + } + export function deviceSerialNumber(): number { + let b = board(); + if (!b) return 42; + let n = 0; + if (b.id) { + n = parseInt(b.id.slice(1)); + if (isNaN(n)) { + n = 0; + for (let i = 0; i < b.id.length; ++i) { + n = ((n << 5) - n) + b.id.charCodeAt(i); + n |= 0; + } + n = Math.abs(n); + } + } + if (!n) n = 42; + return n; + } + export function deviceLongSerialNumber(): RefBuffer { + let b = control.createBuffer(8); + BufferMethods.setNumber(b, BufferMethods.NumberFormat.UInt32LE, 0, deviceSerialNumber()) + return b; + } + export function deviceDalVersion(): string { + return "sim"; + } + export function internalOnEvent(id: number, evid: number, handler: RefAction) { + pxtcore.registerWithDal(id, evid, handler) + } + export function waitForEvent(id: number, evid: number) { + const cb = getResume(); + board().bus.wait(id, evid, cb); + } + + export function allocateNotifyEvent(): number { + let b = board(); + return b.bus.nextNotifyEvent++; + } + + export function raiseEvent(id: number, evid: number, mode: number) { + // TODO mode? + board().bus.queue(id, evid) + } + + export function millis(): number { + return runtime.runningTime(); + } + + export function micros(): number { + return runtime.runningTimeUs() & 0x3fffffff; + } + + export function delayMicroseconds(us: number) { + delay(us / 0.001); + } + + export function createBuffer(size: number) { + return BufferMethods.createBuffer(size) + } + export function dmesg(msg: string) { + console.log(`DMESG: ${msg}`); + } + export function setDebugFlags(flags: number): void { + console.log(`debug flags: ${flags}`); + } + export function heapSnapshot(): void { + console.log(runtime.traceObjects()) + } + + function toStr(v: any) { + if (v instanceof RefRecord) { + return `${v.vtable.name}@${v.id}` + } + + if (v instanceof RefCollection) { + let r = "[" + for (let e of v.toArray()) { + if (r.length > 200) { + r += "..." + break + } + r += toStr(e) + ", " + } + r += "]" + return r + } + + if (typeof v == "function") { + return (v + "").slice(0, 60) + "..." + } + + return v + "" + } + export function dmesgPtr(msg: string, ptr: any) { + console.log(`DMESG: ${msg} ${toStr(ptr)}`); + } + export function dmesgValue(ptr: any) { + console.log(`DMESG: ${toStr(ptr)}`); + } + export function gc() { } + export function profilingEnabled() { + return !!runtime.perfCounters + } + + export function __log(priority: number, str: string) { + let prefix = ""; + switch (priority) { + case 0: prefix = "d>"; break; + case 1: prefix = "l>"; break; + case 2: prefix = "w>"; break; + case 3: prefix = "e>"; break; + } + console.log(prefix + str); + runtime.board.writeSerial(str); + } + + export function heapDump() { + // TODO something better + } + + export function isUSBInitialized() { + return false; + } +} + +// keep in sync with pxtbase.h +namespace pxsim { + export const enum PXT_PANIC { + PANIC_CODAL_OOM = 20, + PANIC_GC_OOM = 21, + PANIC_GC_TOO_BIG_ALLOCATION = 22, + PANIC_CODAL_HEAP_ERROR = 30, + PANIC_CODAL_NULL_DEREFERENCE = 40, + PANIC_CODAL_USB_ERROR = 50, + PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR = 90, + + PANIC_INVALID_BINARY_HEADER = 901, + PANIC_OUT_OF_BOUNDS = 902, + PANIC_REF_DELETED = 903, + PANIC_SIZE = 904, + PANIC_INVALID_VTABLE = 905, + PANIC_INTERNAL_ERROR = 906, + PANIC_NO_SUCH_CONFIG = 907, + PANIC_NO_SUCH_PIN = 908, + PANIC_INVALID_ARGUMENT = 909, + PANIC_MEMORY_LIMIT_EXCEEDED = 910, + PANIC_SCREEN_ERROR = 911, + PANIC_MISSING_PROPERTY = 912, + PANIC_INVALID_IMAGE = 913, + PANIC_CALLED_FROM_ISR = 914, + PANIC_HEAP_DUMPED = 915, + + PANIC_CAST_FIRST = 980, + PANIC_CAST_FROM_UNDEFINED = 980, + PANIC_CAST_FROM_BOOLEAN = 981, + PANIC_CAST_FROM_NUMBER = 982, + PANIC_CAST_FROM_STRING = 983, + PANIC_CAST_FROM_OBJECT = 984, + PANIC_CAST_FROM_FUNCTION = 985, + PANIC_CAST_FROM_NULL = 989, + + } +} \ No newline at end of file diff --git a/libs/base/sim/controlmessage.ts b/libs/base/sim/controlmessage.ts new file mode 100644 index 00000000..8833f395 --- /dev/null +++ b/libs/base/sim/controlmessage.ts @@ -0,0 +1,68 @@ + +namespace pxsim.pxtcore { + // general purpose message sending mechanism + export function sendMessage(channel: string, message: RefBuffer, parentOnly?: boolean) { + if (!channel) return; + + Runtime.postMessage({ + type: "messagepacket", + broadcast: !parentOnly, + channel: channel, + data: message && message.data + } as SimulatorControlMessage) + } + + export function peekMessageChannel(): string { + const state = getControlMessageState(); + const msg = state && state.peek(); + return msg && msg.channel; + } + + export function readMessageData(): RefBuffer { + const state = getControlMessageState(); + const msg = state && state.read(); + return msg && new RefBuffer(msg.data); + } +} + +namespace pxsim { + // keep in sync with ts + export const CONTROL_MESSAGE_EVT_ID = 2999; + export const CONTROL_MESSAGE_RECEIVED = 1; + + export class ControlMessageState { + messages: SimulatorControlMessage[]; + enabled: boolean; + + constructor(private board: CommonBoard) { + this.messages = []; + this.enabled = false; + this.board.addMessageListener(msg => this.messageHandler(msg)); + } + private messageHandler(msg: SimulatorMessage) { + if (msg.type == "messagepacket") { + let packet = msg; + this.enqueue(packet); + } + } + enqueue(message: SimulatorControlMessage) { + this.messages.push(message); + this.board.bus.queue(CONTROL_MESSAGE_EVT_ID, CONTROL_MESSAGE_RECEIVED); + } + peek() { + return this.messages[0]; + } + read() { + return this.messages.shift(); + } + } + + + export interface ControlMessageBoard extends CommonBoard { + controlMessageState: ControlMessageState; + } + + export function getControlMessageState() { + return (board() as ControlMessageBoard).controlMessageState; + } +} \ No newline at end of file diff --git a/libs/base/sim/core.ts b/libs/base/sim/core.ts new file mode 100644 index 00000000..8a59f77d --- /dev/null +++ b/libs/base/sim/core.ts @@ -0,0 +1,14 @@ +/// + +namespace pxsim { + export interface CommonBoard extends CoreBoard + , EdgeConnectorBoard, EventBusBoard { + bus: EventBus; + buttonState: CommonButtonState; + edgeConnectorState: EdgeConnectorState; + } + + export function board(): CommonBoard { + return runtime.board as CommonBoard; + } +} \ No newline at end of file diff --git a/libs/base/sim/loops.ts b/libs/base/sim/loops.ts new file mode 100644 index 00000000..0b82109a --- /dev/null +++ b/libs/base/sim/loops.ts @@ -0,0 +1,4 @@ +namespace pxsim.loops { + export let pause = thread.pause; + export let forever = thread.forever; +} \ No newline at end of file diff --git a/libs/base/sim/tsconfig.json b/libs/base/sim/tsconfig.json new file mode 100644 index 00000000..1db1f5ab --- /dev/null +++ b/libs/base/sim/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2017", + "noImplicitAny": true, + "noImplicitReturns": true, + "lib": [ + "DOM", + "DOM.Iterable", + "ES2017" + ], + "rootDir": ".", + "newLine": "LF", + "sourceMap": false + } +} diff --git a/libs/base/templates.ts b/libs/base/templates.ts new file mode 100644 index 00000000..9c5189b7 --- /dev/null +++ b/libs/base/templates.ts @@ -0,0 +1,5 @@ +/** + * Tagged hex literal converter + */ +//% shim=@hex +function hex(lits: any, ...args: any[]): Buffer { return null } diff --git a/libs/base/test.ts b/libs/base/test.ts new file mode 100644 index 00000000..db39dde0 --- /dev/null +++ b/libs/base/test.ts @@ -0,0 +1,14 @@ +let i = 1 +let f = 0.5 +let plus = i + f +let minus = i - f + +let r = Math.random() +let ri = Math.randomRange(5, 10) + + +function check(cond:boolean) { control.assert(cond, 108) } + +check(Buffer.pack("<2h", [0x3412, 0x7856]).toHex() == "12345678") +check(Buffer.pack(">hh", [0x3412, 0x7856]).toHex() == "34127856") +check(Buffer.fromHex("F00d").toHex() == "f00d") \ No newline at end of file diff --git a/libs/base/trig.cpp b/libs/base/trig.cpp new file mode 100644 index 00000000..7c95e2f0 --- /dev/null +++ b/libs/base/trig.cpp @@ -0,0 +1,37 @@ +#include "pxtbase.h" +#include +#include + +using namespace std; + +namespace Math_ { + +#define SINGLE(op) return fromDouble(::op(toDouble(x))); + +//% +TNumber atan2(TNumber y, TNumber x) { + return fromDouble(::atan2(toDouble(y), toDouble(x))); +} + +//% +TNumber tan(TNumber x){SINGLE(tan)} + +//% +TNumber sin(TNumber x){SINGLE(sin)} + +//% +TNumber cos(TNumber x){SINGLE(cos)} + +//% +TNumber atan(TNumber x){SINGLE(atan)} + +//% +TNumber asin(TNumber x){SINGLE(asin)} + +//% +TNumber acos(TNumber x){SINGLE(acos)} + +//% +TNumber sqrt(TNumber x){SINGLE(sqrt)} + +} \ No newline at end of file diff --git a/libs/base/utfdecoder.ts b/libs/base/utfdecoder.ts new file mode 100644 index 00000000..b459f4d0 --- /dev/null +++ b/libs/base/utfdecoder.ts @@ -0,0 +1,83 @@ +class UTF8Decoder { + private buf: Buffer; + + constructor() { + this.buf = undefined; + } + + add(buf: Buffer) { + if (!buf || !buf.length) return; + + if (!this.buf) + this.buf = buf; + else { + const b = control.createBuffer(this.buf.length + buf.length); + b.write(0, this.buf); + b.write(this.buf.length, buf); + this.buf = b; + } + } + + decodeUntil(delimiter: number): string { + if (!this.buf) return undefined; + delimiter = delimiter | 0; + let i = 0; + for (; i < this.buf.length; ++i) { + const c = this.buf[i]; + // skip multi-chars + if ((c & 0xe0) == 0xc0) + i += 1; + else if ((c & 0xf0) == 0xe0) + i += 2; + else if (c == delimiter) { + // found it + break; + } + } + + if (i >= this.buf.length) + return undefined; + else { + const s = this.buf.slice(0, i).toString(); + if (i + 1 == this.buf.length) + this.buf = undefined; + else + this.buf = this.buf.slice(i + 1); + return s; + } + } + + decode(): string { + if (!this.buf) return ""; + + // scan the end of the buffer for partial characters + let length = 0; + for (let i = this.buf.length - 1; i >= 0; i--) { + const c = this.buf[i]; + if ((c & 0x80) == 0) { + length = i + 1; + break; + } + else if ((c & 0xe0) == 0xc0) { + length = i + 2; + break; + } + else if ((c & 0xf0) == 0xe0) { + length = i + 3; + break; + } + } + // is last beyond the end? + if (length == this.buf.length) { + const s = this.buf.toString(); + this.buf = undefined; + return s; + } else if (length == 0) { // data yet + return ""; + } else { + const s = this.buf.slice(0, length).toString(); + this.buf = this.buf.slice(length); + return s; + } + } +} \ No newline at end of file diff --git a/libs/buttons/_locales/buttons-jsdoc-strings.json b/libs/buttons/_locales/buttons-jsdoc-strings.json deleted file mode 100755 index aaeb5ecd..00000000 --- a/libs/buttons/_locales/buttons-jsdoc-strings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Button.id": "Gets the component identifier for the button", - "Button.isPressed": "Check if a button is pressed or not.", - "Button.onEvent": "Do something when a button (`A`, `B` or both `A` + `B`) is clicked, double clicked, etc...", - "Button.onEvent|param|body": "code to run when the event is raised", - "Button.wasPressed": "See if the button was pressed again since the last time you checked.", - "ButtonEvent": "User interaction on buttons", - "DigitalInOutPin.pushButton": "Get the push button (connected to GND) for given pin", - "jacdac": "A Joint Asynchronous Communications, Device Agnostic Control.", - "jacdac.attachButtonToController": "Connects the events of the button to the controller button", - "jacdac.attachButtonToController|param|controllerButton": "@param button " -} \ No newline at end of file diff --git a/libs/buttons/_locales/buttons-strings.json b/libs/buttons/_locales/buttons-strings.json deleted file mode 100755 index 2b3a42d4..00000000 --- a/libs/buttons/_locales/buttons-strings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "Button.isPressed|block": "%button|is pressed", - "Button.onEvent|block": "on %button|%event", - "Button.wasPressed|block": "%button|was pressed", - "ButtonEvent.Click|block": "click", - "ButtonEvent.Down|block": "down", - "ButtonEvent.LongClick|block": "long click", - "ButtonEvent.Up|block": "up", - "jacdac.attachButtonToController|block": "jacdac attach $button to controller $controllerButton", - "jacdac|block": "jacdac", - "{id:category}Button": "Button", - "{id:category}DigitalInOutPin": "DigitalInOutPin", - "{id:category}Input": "Input", - "{id:category}Jacdac": "Jacdac", - "{id:group}Controller": "Controller", - "{id:group}More": "More" -} \ No newline at end of file diff --git a/libs/buttons/enums.d.ts b/libs/buttons/enums.d.ts deleted file mode 100755 index 782d9037..00000000 --- a/libs/buttons/enums.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Auto-generated. Do not edit. - - - /** - * User interaction on buttons - */ - - declare const enum ButtonEvent { - //% block="click" - Click = 3, // DEVICE_BUTTON_EVT_CLICK - //% block="long click" - LongClick = 4, // DEVICE_BUTTON_EVT_LONG_CLICK - //% block="up" - Up = 2, // DEVICE_BUTTON_EVT_UP - //% block="down" - Down = 1, // DEVICE_BUTTON_EVT_DOWN - } - -// Auto-generated. Do not edit. Really. diff --git a/libs/buttons/pxt.json b/libs/buttons/pxt.json deleted file mode 100755 index 694d79cd..00000000 --- a/libs/buttons/pxt.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "buttons", - "description": "Button A and B drivers", - "dependencies": { - "core": "file:../core", - "jacdac": "file:../jacdac" - }, - "files": [ - "README.md", - "buttons.cpp", - "jacdac.ts", - "shims.d.ts", - "enums.d.ts" - ], - "testFiles": [ - "test.ts" - ], - "public": true, - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/buttons" -} diff --git a/libs/buttons/shims.d.ts b/libs/buttons/shims.d.ts deleted file mode 100755 index a84b08bd..00000000 --- a/libs/buttons/shims.d.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Auto-generated. Do not edit. - - -declare interface DigitalInOutPin { - /** - * Get the push button (connected to GND) for given pin - */ - //% shim=DigitalInOutPinMethods::pushButton - pushButton(): Button; -} - - - - //% noRefCounting fixedInstances -declare interface Button { - /** - * Do something when a button (`A`, `B` or both `A` + `B`) is clicked, double clicked, etc... - * @param button the button that needs to be clicked or used - * @param event the kind of button gesture that needs to be detected - * @param body code to run when the event is raised - */ - //% help=input/button/on-event - //% blockId=buttonEvent block="on %button|%event" - //% blockNamespace=input - //% button.fieldEditor="gridpicker" - //% button.fieldOptions.width=220 - //% button.fieldOptions.columns=3 - //% weight=96 blockGap=12 - //% trackArgs=0 shim=ButtonMethods::onEvent - onEvent(ev: ButtonEvent, body: () => void): void; - - /** - * Check if a button is pressed or not. - * @param button the button to query the request - */ - //% help=input/button/is-pressed - //% block="%button|is pressed" - //% blockId=buttonIsPressed - //% blockNamespace=input - //% button.fieldEditor="gridpicker" - //% button.fieldOptions.width=220 - //% button.fieldOptions.columns=3 - //% weight=50 blockGap=8 - //% trackArgs=0 shim=ButtonMethods::isPressed - isPressed(): boolean; - - /** - * See if the button was pressed again since the last time you checked. - * @param button the button to query the request - */ - //% help=input/button/was-pressed - //% block="%button|was pressed" - //% blockId=buttonWasPressed - //% blockNamespace=input - //% button.fieldEditor="gridpicker" - //% button.fieldOptions.width=220 - //% button.fieldOptions.columns=3 - //% group="More" weight=46 blockGap=8 - //% trackArgs=0 shim=ButtonMethods::wasPressed - wasPressed(): boolean; - - /** - * Gets the component identifier for the button - */ - //% shim=ButtonMethods::id - id(): int32; -} - -// Auto-generated. Do not edit. Really. diff --git a/libs/core---nrf52/dal.d.ts b/libs/core---nrf52/dal.d.ts index 25c967cd..df88f125 100644 --- a/libs/core---nrf52/dal.d.ts +++ b/libs/core---nrf52/dal.d.ts @@ -1,137 +1,18 @@ // Auto-generated. Do not edit. declare const enum DAL { - // /libraries/codal-core/inc/JACDAC/JACDAC.h - JD_STARTED = 2, - JD_SERVICE_ARRAY_SIZE = 20, // /libraries/codal-core/inc/JACDAC/JDPhysicalLayer.h - JD_VERSION = 0, - JD_BYTE_AT_125KBAUD = 80, - JD_MIN_INTERLODATA_SPACING = 40, - JD_SERIAL_MAX_BUFFERS = 10, - JD_SERIAL_MAX_SERVICE_NUMBER = 15, - JD_SERIAL_RECEIVING = 1, - JD_SERIAL_RECEIVING_HEADER = 2, - JD_SERIAL_TRANSMITTING = 4, - JD_SERIAL_RX_LO_PULSE = 8, - JD_SERIAL_TX_LO_PULSE = 16, - JD_SERIAL_BUS_LO_ERROR = 32, - JD_SERIAL_BUS_TIMEOUT_ERROR = 64, - JD_SERIAL_BUS_UART_ERROR = 128, - JD_SERIAL_ERR_MSK = 224, - JD_SERIAL_BUS_STATE = 256, - JD_SERIAL_BUS_TOGGLED = 512, - JD_SERIAL_DEBUG_BIT = 32768, - JD_SERIAL_EVT_DATA_READY = 1, - JD_SERIAL_EVT_BUS_ERROR = 2, - JD_SERIAL_EVT_CRC_ERROR = 3, - JD_SERIAL_EVT_DRAIN = 4, - JD_SERIAL_EVT_RX_TIMEOUT = 5, - JD_SERIAL_EVT_BUS_CONNECTED = 5, - JD_SERIAL_EVT_BUS_DISCONNECTED = 6, - JD_SERIAL_HEADER_SIZE = 4, - JD_SERIAL_CRC_HEADER_SIZE = 2, - JD_SERIAL_MAX_PAYLOAD_SIZE = 255, - JD_SERIAL_MAXIMUM_BUFFERS = 10, - JD_SERIAL_DMA_TIMEOUT = 2, - JD_SERIAL_MAX_BAUD = 1000000, - JD_SERIAL_TX_MAX_BACKOFF = 1000, - JD_RX_ARRAY_SIZE = 10, - JD_TX_ARRAY_SIZE = 10, - JD_SERIAL_BAUD_1M = 1, - JD_SERIAL_BAUD_500K = 2, - JD_SERIAL_BAUD_250K = 4, - JD_SERIAL_BAUD_125K = 8, Receiving = 0, Transmitting = 1, + Error = 2, Unknown = 3, ListeningForPulse = 0, ErrorRecovery = 1, Off = 2, - Baud1M = 1, - Baud500K = 2, - Baud250K = 4, - Baud125K = 8, Continuation = 0, - BusLoError = 32, - BusTimeoutError = 64, - BusUARTError = 128, - // /libraries/codal-core/inc/JACDAC/JDService.h - JD_MAX_HOST_SERVICES = 16, - JD_SERVICE_EVT_CONNECTED = 65520, - JD_SERVICE_EVT_DISCONNECTED = 65521, - JD_SERVICE_EVT_ERROR = 65526, - JD_SERVICE_NUMBER_UNINITIALISED_VAL = 65535, - JD_SERVICE_STATUS_FLAGS_INITIALISED = 2, - JD_SERVICE_INFO_HEADER_SIZE = 6, - JD_SERVICE_MODE_CLIENT = 1, - JD_SERVICE_MODE_HOST = 2, - JD_SERVICE_MODE_BROADCAST_HOST = 3, - JD_SERVICE_MODE_CONTROL_LAYER = 4, - ClientService = 1, - HostService = 2, - BroadcastHostService = 3, - ControlLayerService = 4, // /libraries/codal-core/inc/JACDAC/JDServiceClasses.h STATIC_CLASS_START = 0, STATIC_CLASS_END = 16777215, DYNAMIC_CLASS_END = 4294967295, - JD_SERVICE_CLASS_CODAL_START = 0, - JD_SERVICE_CLASS_CODAL_END = 2000, - JD_SERVICE_CLASS_MAKECODE_START = 2000, - JD_SERVICE_CLASS_MAKECODE_END = 4000, - JD_SERVICE_CLASS_CONTROL = 0, - JD_SERVICE_CLASS_CONTROL_RNG = 1, - JD_SERVICE_CLASS_CONTROL_CONFIGURATION = 2, - JD_SERVICE_CLASS_CONTROL_TEST = 3, - JD_SERVICE_CLASS_JOYSTICK = 4, - JD_SERVICE_CLASS_MESSAGE_BUS = 5, - JD_SERVICE_CLASS_BRIDGE = 6, - JD_SERVICE_CLASS_BUTTON = 7, - JD_SERVICE_CLASS_ACCELEROMETER = 8, - JD_SERVICE_CLASS_CONSOLE = 9, - // /libraries/codal-core/inc/JACDAC/control/JDCRC.h - JD_CRC_POLYNOMIAL = 3859, - // /libraries/codal-core/inc/JACDAC/control/JDConfigurationService.h - JD_CONTROL_CONFIGURATION_SERVICE_NUMBER = 1, - JD_CONTROL_CONFIGURATION_SERVICE_REQUEST_TYPE_NAME = 1, - JD_CONTROL_CONFIGURATION_SERVICE_REQUEST_TYPE_IDENTIFY = 2, - JD_CONTROL_CONFIGURATION_SERVICE_PACKET_HEADER_SIZE = 2, - JD_CONTROL_CONFIGURATION_EVT_NAME = 1, - JD_CONTROL_CONFIGURATION_EVT_IDENTIFY = 2, - JD_DEFAULT_INDICATION_TIME = 5, - // /libraries/codal-core/inc/JACDAC/control/JDControlService.h - JD_CONTROL_SERVICE_STATUS_ENUMERATE = 2, - JD_CONTROL_SERVICE_STATUS_ENUMERATING = 4, - JD_CONTROL_SERVICE_STATUS_ENUMERATED = 8, - JD_CONTROL_SERVICE_STATUS_BUS_LO = 16, - JD_CONTROL_SERVICE_EVT_CHANGED = 2, - JD_CONTROL_SERVICE_EVT_TIMER_CALLBACK = 3, - JD_CONTROL_PACKET_HEADER_SIZE = 10, - JD_CONTROL_ROLLING_TIMEOUT_VAL = 3, - // /libraries/codal-core/inc/JACDAC/control/JDDeviceManager.h - JD_DEVICE_FLAGS_NACK = 8, - JD_DEVICE_FLAGS_HAS_NAME = 4, - JD_DEVICE_FLAGS_PROPOSING = 2, - JD_DEVICE_FLAGS_REJECT = 1, - JD_DEVICE_MAX_HOST_SERVICES = 16, - JD_DEVICE_DEFAULT_COMMUNICATION_RATE = 1, - // /libraries/codal-core/inc/JACDAC/control/JDRNGService.h - JD_CONTROL_RNG_SERVICE_NUMBER = 2, - JD_CONTROL_RNG_SERVICE_REQUEST_TYPE_REQ = 1, - JD_CONTROL_RNG_SERVICE_REQUEST_TYPE_RESP = 2, - // /libraries/codal-core/inc/JACDAC/services/JDAccelerometerService.h - JD_ACCEL_EVT_SEND_DATA = 1, - // /libraries/codal-core/inc/JACDAC/services/JDConsoleService.h - JD_CONSOLE_LOG_PRIORITY_LOG = 1, - JD_CONSOLE_LOG_PRIORITY_INFO = 2, - JD_CONSOLE_LOG_PRIORITY_DEBUG = 3, - JD_CONSOLE_LOG_PRIORITY_ERROR = 4, - Log = 1, - Info = 2, - Debug = 3, - // /libraries/codal-core/inc/JACDAC/services/JDMessageBusService.h - JD_MESSAGEBUS_TYPE_EVENT = 1, - JD_MESSAGEBUS_TYPE_LISTEN = 2, // /libraries/codal-core/inc/core/CodalComponent.h DEVICE_ID_BUTTON_A = 1, DEVICE_ID_BUTTON_B = 2, @@ -448,51 +329,9 @@ declare const enum DAL { MATRIX_DISPLAY_ROTATION_180 = 2, MATRIX_DISPLAY_ROTATION_270 = 3, NO_CONN = 0, - // /libraries/codal-core/inc/drivers/MAG3110.h - MAG3110_DEFAULT_ADDR = 29, - MAG_DR_STATUS = 0, - MAG_OUT_X_MSB = 1, - MAG_OUT_X_LSB = 2, - MAG_OUT_Y_MSB = 3, - MAG_OUT_Y_LSB = 4, - MAG_OUT_Z_MSB = 5, - MAG_OUT_Z_LSB = 6, - MAG_WHOAMI = 7, - MAG_SYSMOD = 8, - MAG_OFF_X_MSB = 9, - MAG_OFF_X_LSB = 10, - MAG_OFF_Y_MSB = 11, - MAG_OFF_Y_LSB = 12, - MAG_OFF_Z_MSB = 13, - MAG_OFF_Z_LSB = 14, - MAG_DIE_TEMP = 15, - MAG_CTRL_REG1 = 16, - MAG_CTRL_REG2 = 17, - MAG3110_SAMPLE_RATES = 11, - MAG3110_WHOAMI_VAL = 196, - // /libraries/codal-core/inc/drivers/MMA8453.h - MMA8453_DEFAULT_ADDR = 56, - MMA8453_WHOAMI_VAL = 58, // /libraries/codal-core/inc/drivers/MMA8653.h MICROBIT_ACCEL_PITCH_ROLL_VALID = 2, MICROBIT_ACCEL_ADDED_TO_IDLE = 4, - MMA8653_DEFAULT_ADDR = 58, - MMA8653_STATUS = 0, - MMA8653_OUT_X_MSB = 1, - MMA8653_WHOAMI = 13, - MMA8653_XYZ_DATA_CFG = 14, - MMA8653_CTRL_REG1 = 42, - MMA8653_CTRL_REG2 = 43, - MMA8653_CTRL_REG3 = 44, - MMA8653_CTRL_REG4 = 45, - MMA8653_CTRL_REG5 = 46, - MMA8653_WHOAMI_VAL = 90, - MMA8653_SAMPLE_RANGES = 3, - MMA8653_SAMPLE_RATES = 8, - // /libraries/codal-core/inc/drivers/MPU6050.h - MPU6050_DEFAULT_ADDR = 104, - MPU6050_WHOAMI = 117, - MPU6050_WHOAMI_VAL = 52, // /libraries/codal-core/inc/drivers/MultiButton.h MULTI_BUTTON_STATE_1 = 1, MULTI_BUTTON_STATE_2 = 2, @@ -501,14 +340,6 @@ declare const enum DAL { MULTI_BUTTON_SUPRESSED_1 = 16, MULTI_BUTTON_SUPRESSED_2 = 32, MULTI_BUTTON_ATTACHED = 64, - // /libraries/codal-core/inc/drivers/ST7735.h - MADCTL_MY = 128, - MADCTL_MX = 64, - MADCTL_MV = 32, - MADCTL_ML = 16, - MADCTL_RGB = 0, - MADCTL_BGR = 8, - MADCTL_MH = 4, // /libraries/codal-core/inc/drivers/TouchButton.h TOUCH_BUTTON_CALIBRATION_PERIOD = 10, TOUCH_BUTTON_CALIBRATION_LINEAR_OFFSET = 2, @@ -718,6 +549,8 @@ declare const enum DAL { LEVEL_DETECTOR_SPL_HIGH_THRESHOLD_PASSED = 2, LEVEL_DETECTOR_SPL_LOW_THRESHOLD_PASSED = 4, LEVEL_DETECTOR_SPL_DEFAULT_WINDOW_SIZE = 128, + // /libraries/codal-core/inc/streams/MemorySource.h + MEMORY_SOURCE_MAX_BUFFER = 256, // /libraries/codal-core/inc/streams/Synthesizer.h SYNTHESIZER_SAMPLE_RATE = 44100, TONE_WIDTH = 1024, @@ -856,6 +689,7 @@ declare const enum DAL { ACCELEROMETER_TYPE_MPU6050 = 104, DISPLAY_TYPE_ST7735 = 7735, DISPLAY_TYPE_ILI9341 = 9341, + DISPLAY_TYPE_SMART = 4242, CFG_PIN_A0 = 100, CFG_PIN_A1 = 101, CFG_PIN_A2 = 102, @@ -939,6 +773,30 @@ declare const enum DAL { CFG_ANALOG_JOYSTICK_MIN = 216, CFG_ANALOG_JOYSTICK_MAX = 217, CFG_TIMERS_TO_USE = 218, + CFG_PIN_ONBOARD_DOTSTAR_CLOCK = 219, + CFG_PIN_ONBOARD_DOTSTAR_DATA = 220, + CFG_NUM_ONBOARD_DOTSTARS = 221, + CFG_PIN_ONBOARD_NEOPIXEL = 222, + CFG_NUM_ONBOARD_NEOPIXELS = 223, + CFG_MATRIX_KEYPAD_MESSAGE_ID = 239, + CFG_NUM_MATRIX_KEYPAD_ROWS = 240, + CFG_PIN_MATRIX_KEYPAD_ROW0 = 241, + CFG_PIN_MATRIX_KEYPAD_ROW1 = 242, + CFG_PIN_MATRIX_KEYPAD_ROW2 = 243, + CFG_PIN_MATRIX_KEYPAD_ROW3 = 244, + CFG_PIN_MATRIX_KEYPAD_ROW4 = 245, + CFG_PIN_MATRIX_KEYPAD_ROW5 = 246, + CFG_PIN_MATRIX_KEYPAD_ROW6 = 247, + CFG_PIN_MATRIX_KEYPAD_ROW7 = 248, + CFG_NUM_MATRIX_KEYPAD_COLS = 250, + CFG_PIN_MATRIX_KEYPAD_COL0 = 251, + CFG_PIN_MATRIX_KEYPAD_COL1 = 252, + CFG_PIN_MATRIX_KEYPAD_COL2 = 253, + CFG_PIN_MATRIX_KEYPAD_COL3 = 254, + CFG_PIN_MATRIX_KEYPAD_COL4 = 255, + CFG_PIN_MATRIX_KEYPAD_COL5 = 256, + CFG_PIN_MATRIX_KEYPAD_COL6 = 257, + CFG_PIN_MATRIX_KEYPAD_COL7 = 258, CFG_PIN_B0 = 300, CFG_PIN_B1 = 301, CFG_PIN_B2 = 302, @@ -1051,8 +909,60 @@ declare const enum DAL { CFG_PIN_LCD_DATALINE7 = 1014, CFG_NUM_LCD_COLUMNS = 1015, CFG_NUM_LCD_ROWS = 1016, + CFG_PIN_RCC0 = 1017, + CFG_PIN_RCC1 = 1018, + CFG_PIN_RCC2 = 1019, + CFG_PIN_RCC3 = 1020, + CFG_PIN_RCC4 = 1021, + CFG_PIN_RCC5 = 1022, + CFG_PIN_RCC6 = 1023, + CFG_PIN_RCC7 = 1024, + CFG_PIN_SERVO0 = 1025, + CFG_PIN_SERVO1 = 1026, + CFG_PIN_SERVO2 = 1027, + CFG_PIN_SERVO3 = 1028, + CFG_PIN_SERVO4 = 1029, + CFG_PIN_SERVO5 = 1030, + CFG_PIN_SERVO6 = 1031, + CFG_PIN_SERVO7 = 1032, + CFG_PIN_SERVO8 = 1033, + CFG_PIN_PI_TX = 1034, + CFG_PIN_PI_RX = 1035, + CFG_PIN_GPS_SDA = 1036, + CFG_PIN_GPS_SCL = 1037, + CFG_PIN_GPS_TX = 1038, + CFG_PIN_GPS_RX = 1039, + CFG_PIN_GROVE0 = 1040, + CFG_PIN_GROVE1 = 1041, + CFG_PIN_SS = 1042, + CFG_PIN_JDPWR_PRE_SENSE = 1100, + CFG_PIN_JDPWR_GND_SENSE = 1101, + CFG_PIN_JDPWR_PULSE = 1102, + CFG_PIN_JDPWR_OVERLOAD_LED = 1103, + CFG_PIN_JDPWR_ENABLE = 1104, + CFG_PIN_JDPWR_FAULT = 1105, // /pxtapp/hf2dbg.h HF2DBG_H = 1, + // /pxtapp/jacdac-services/jdprotocol.h + JDSPI_MAGIC = 31437, + JDSPI_MAGIC_NOOP = 46029, + // /pxtapp/mixer---nrf52/melody.h + OUTPUT_BITS = 10, + SW_TRIANGLE = 1, + SW_SAWTOOTH = 2, + SW_SINE = 3, + SW_TUNEDNOISE = 4, + SW_NOISE = 5, + SW_SQUARE_10 = 11, + SW_SQUARE_50 = 15, + SW_SQUARE_CYCLE_16 = 16, + SW_SQUARE_CYCLE_32 = 17, + SW_SQUARE_CYCLE_64 = 18, + CODAL = 1, + MAX_SOUNDS = 5, + Waiting = 0, + Playing = 1, + Done = 2, // /pxtapp/pins.h BUTTON_ACTIVE_HIGH_PULL_DOWN = 17, BUTTON_ACTIVE_HIGH_PULL_UP = 33, @@ -1136,10 +1046,13 @@ declare const enum DAL { P1_30 = 62, P1_31 = 63, // /pxtapp/pxt.h + PXT_COMM_BASE = 536879104, DEVICE_ID_BUTTON_SLIDE = 3000, DEVICE_ID_MICROPHONE = 3001, DEVICE_ID_FIRST_BUTTON = 4000, DEVICE_ID_FIRST_TOUCHBUTTON = 4100, + PXT_INTERNAL_KEY_UP = 2050, + PXT_INTERNAL_KEY_DOWN = 2051, // /pxtapp/pxtbase.h PXT32 = 1, PXT64 = 1, @@ -1184,6 +1097,11 @@ declare const enum DAL { GC = 0, // /pxtapp/pxtconfig.h PXT_UF2_FAMILY = 2913282112, + // /pxtapp/settings/Flash.h + DEVICE_FLASH_ERROR = 922, + // /pxtapp/settings/RAFFS.h + RAFFS_FOLLOWING_MASK = 32768, + RAFFS_FLASH_BUFFER_SIZE = 64, // /pxtapp/uf2format.h BOOTLOADER_START = 0, BOOTLOADER_END = 8192, diff --git a/libs/core---nrf52/led.cpp b/libs/core---nrf52/led.cpp index f4358443..d382cd10 100644 --- a/libs/core---nrf52/led.cpp +++ b/libs/core---nrf52/led.cpp @@ -1,10 +1,9 @@ #include "pxt.h" -#include "led.h" - +#include "pxtbase.h" namespace pxt { -TeknikioDevice bluebird; + TeknikioDevice bluebird; void initTeknikio() { bluebird.init(); @@ -14,7 +13,8 @@ TeknikioDevice bluebird; //% color=#7600A8 weight=101 icon="\uf205" namespace led { - + + extern TeknikioDevice bluebird; typedef uint32_t ImageLiteral_; /** * Draws an image on the LED screen. diff --git a/libs/core---nrf52/led.h b/libs/core---nrf52/led.h index a0d8c350..aface3ae 100644 --- a/libs/core---nrf52/led.h +++ b/libs/core---nrf52/led.h @@ -1,19 +1,19 @@ -#include "Display.h" -#include "TeknikioDevice.h" -#include "pxtbase.h" -//#include "MicroBitImage.h" +// #include "Display.h" +// #include "TeknikioDevice.h" +// #include "pxtbase.h" +// //#include "MicroBitImage.h" -namespace pxt { +// namespace pxt { -void initTeknikio(); +// void initTeknikio(); -}; +// }; -#undef PXT_MAIN -#define PXT_MAIN \ - int main() { \ - pxt::initTeknikio(); \ - pxt::start(); \ - return 0; \ - } \ No newline at end of file +// #undef PXT_MAIN +// #define PXT_MAIN +// int main() { +// pxt::initTeknikio(); +// pxt::start(); +// return 0; +// } \ No newline at end of file diff --git a/libs/core---nrf52/pxt.json b/libs/core---nrf52/pxt.json index 1e0265db..500586e5 100644 --- a/libs/core---nrf52/pxt.json +++ b/libs/core---nrf52/pxt.json @@ -54,8 +54,6 @@ "additionalFilePath": "../../node_modules/pxt-common-packages/libs/core---nrf52", "cppDependencies": { "accelerometer": "file:../accelerometer", - "buttons": "file:../buttons", - "jacdac": "file:../jacdac", "lightsensor": "file:../lightsensor", "switch": "file:../switch", "mixer---nrf52": "file:../mixer---nrf52" diff --git a/libs/core---nrf52832/_locales/core---nrf52832-jsdoc-strings.json b/libs/core---nrf52832/_locales/core---nrf52832-jsdoc-strings.json deleted file mode 100755 index b7ed718e..00000000 --- a/libs/core---nrf52832/_locales/core---nrf52832-jsdoc-strings.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "AnalogInPin.analogRead": "Read the connector value as analog, that is, as a value comprised between 0 and 1023.", - "AnalogOutPin.analogWrite": "Set the connector value as analog. Value must be comprised between 0 and 1023.", - "AnalogOutPin.analogWrite|param|value": "value to write to the pin between ``0`` and ``1023``. eg:1023,0", - "DigitalInOutPin.digitalRead": "Read a pin or connector as either 0 or 1", - "DigitalInOutPin.digitalWrite": "Set a pin or connector value to either 0 or 1.", - "DigitalInOutPin.digitalWrite|param|value": "value to set on the pin", - "DigitalInOutPin.onEvent": "Register code to run when a pin event occurs.", - "DigitalInOutPin.onPulsed": "Make this pin a digital input, and create events where the timestamp is the duration\nthat this pin was either ``high`` or ``low``.", - "DigitalInOutPin.pulseIn": "Return the duration of a pulse in microseconds", - "DigitalInOutPin.pulseIn|param|value": "the value of the pulse (default high)", - "DigitalInOutPin.setPull": "Set the pull direction of this pin.", - "DigitalInOutPin.setPull|param|pull": "one of the mbed pull configurations: PullUp, PullDown, PullNone", - "PwmOnlyPin.analogSetPeriod": "Set the Pulse-width modulation (PWM) period of the analog output. The period is in\n**microseconds** or `1/1000` milliseconds.\nIf this pin is not configured as an analog output (using `analog write pin`), the operation has\nno effect.", - "PwmOnlyPin.servoSetPulse": "Set the pin for PWM analog output, make the period be 20 ms, and set the pulse width.\nThe pulse width is based on the value it is given **microseconds** or `1/1000` milliseconds.", - "PwmOnlyPin.servoSetPulse|param|duration": "pulse duration in micro seconds, eg:1500", - "PwmOnlyPin.servoWrite": "Write a value to the servo to control the rotation of the shaft. On a standard servo, this will\nset the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous\nrotation servo, this will set the speed of the servo (with ``0`` being full-speed in one\ndirection, ``180`` being full speed in the other, and a value near ``90`` being no movement).", - "PwmOnlyPin.servoWrite|param|value": "angle or rotation speed", - "SPI.setFrequency": "Sets the SPI clock frequency", - "SPI.setMode": "Sets the SPI bus mode", - "SPI.transfer": "Transfer buffers over the SPI bus", - "SPI.write": "Write to the SPI bus", - "configStorage.clear": "Clears the local storage", - "configStorage.getBuffer": "Gets an entry from the device storage. Key may have up to 16 characters (bytes).", - "configStorage.getBuffer|param|key": "the identifier (max 16 characters)", - "configStorage.getItem": "Stores the value at the key entry", - "configStorage.getItem|param|key": "identifier of the key (max 16 characters)", - "configStorage.removeItem": "Removes the key from local storage", - "configStorage.removeItem|param|key": "the identifier (max 16 characters)", - "configStorage.setBuffer": "Puts an entry in the device storage. Key may have up to 16 characters (bytes).", - "configStorage.setBuffer|param|key": "the identifier (max 16 characters)", - "configStorage.setBuffer|param|value": "the data (max 32 characters)", - "configStorage.setItem": "Stores the value at the key entry", - "configStorage.setItem|param|key": "identifier of the key (max 16 characters)", - "configStorage.setItem|param|value": "identifier of the value (max 32 characters)", - "control": "Program controls and events.", - "control.Timer": "A timer", - "control.Timer.millis": "Gets the elapsed time in millis since the last reset", - "control.Timer.pauseUntil": "Pauses until the timer reaches the given amount of milliseconds", - "control.Timer.pauseUntil|param|ms": "how long to pause for, eg: 5, 100, 200, 500, 1000, 2000", - "control.Timer.reset": "Resets the timer", - "control.Timer.seconds": "Gets the elapsed time in seconds since the last reset", - "control.allocateNotifyEvent": "Allocates the next user notification event", - "control.deviceDalVersion": "Determine the version of system software currently running.", - "control.dmesg": "Write a message to DMESG debugging buffer.", - "control.dmesgPtr": "Write a message and value (pointer) to DMESG debugging buffer.", - "control.isUSBInitialized": "Determines if the USB has been enumerated.", - "control.raiseEvent": "Announce that an event happened to registered handlers.", - "control.raiseEvent|param|src": "ID of the MicroBit Component that generated the event", - "control.raiseEvent|param|value": "Component specific code indicating the cause of the event.", - "light.sendBuffer": "Send a programmable light buffer to the specified digital pin", - "light.sendBuffer|param|buf": "The buffer to send to the pin", - "light.sendBuffer|param|clk": "the clock line if nay", - "light.sendBuffer|param|data": "The pin that the light are connected to", - "light.sendBuffer|param|mode": "the color encoding mode", - "pins": "Control currents in Pins for analog/digital signals, servos, i2c, ...", - "pins.createBuffer": "Create a new zero-initialized buffer.", - "pins.createBuffer|param|size": "number of bytes in the buffer", - "pins.createSPI": "Opens a SPI driver", - "pins.pinByCfg": "Get a pin by configuration id (DAL.CFG_PIN...)", - "pins.pulseDuration": "Get the duration of the last pulse in microseconds. This function should be called from a\n``onPulsed`` handler.", - "pins.spi": "Gets the default SPI driver", - "pins.spiFrequency": "Set the SPI frequency", - "pins.spiFrequency|param|frequency": "the clock frequency, eg: 1000000", - "pins.spiMode": "Set the SPI signal mode", - "pins.spiMode|param|mode": "the mode, eg: 3", - "pins.spiTransfer": "Write a given command to SPI bus, and afterwards read the response.", - "pins.spiWrite": "Write to the SPI slave and return the response", - "pins.spiWrite|param|value": "Data to be sent to the SPI slave" -} \ No newline at end of file diff --git a/libs/core---nrf52832/_locales/core---nrf52832-strings.json b/libs/core---nrf52832/_locales/core---nrf52832-strings.json deleted file mode 100755 index bf0eae63..00000000 --- a/libs/core---nrf52832/_locales/core---nrf52832-strings.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "AnalogInPin.analogRead|block": "analog read|pin %name", - "AnalogOutPin.analogWrite|block": "analog write|pin %name|to %value", - "DigitalInOutPin.digitalRead|block": "digital read|pin %name", - "DigitalInOutPin.digitalWrite|block": "digital write|pin %name|to %value=toggleHighLow", - "DigitalInOutPin.onEvent|block": "on|pin %pin|%event", - "DigitalInOutPin.onPulsed|block": "on|pin %pin|pulsed %pulse", - "DigitalInOutPin.pulseIn|block": "pulse in (µs)|pin %name|pulsed %high||timeout %maxDuration (us)", - "DigitalInOutPin.setPull|block": "set pull|pin %pin|to %pull", - "PinEvent.Fall|block": "fall", - "PinEvent.PulseHigh|block": "pulse high", - "PinEvent.PulseLow|block": "pulse low", - "PinEvent.Rise|block": "rise", - "PinPullMode.PullDown|block": "down", - "PinPullMode.PullNone|block": "none", - "PinPullMode.PullUp|block": "up", - "PulseValue.High|block": "high", - "PulseValue.Low|block": "low", - "PwmOnlyPin.analogSetPeriod|block": "analog set period|pin %pin|to (µs)%period", - "PwmOnlyPin.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %duration", - "PwmOnlyPin.servoWrite|block": "servo write|pin %name|to %value=protractorPicker", - "configStorage|block": "configStorage", - "control.Timer.millis|block": "%timer|millis", - "control.Timer.pauseUntil|block": "%timer|pause until (ms) %ms", - "control.Timer.reset|block": "%timer|reset", - "control.Timer.seconds|block": "%timer|seconds", - "control.deviceDalVersion|block": "device dal version", - "control.raiseEvent|block": "raise event|from %src|with value %value", - "control.timer1|block": "timer 1", - "control.timer2|block": "timer 2", - "control.timer3|block": "timer 3", - "control.timer4|block": "timer 4", - "control.timer5|block": "timer 5", - "control.timer6|block": "timer 6", - "control.timer7|block": "timer 7", - "control.timer8|block": "timer 8", - "control|block": "control", - "light|block": "light", - "pins.pulseDuration|block": "pulse duration (µs)", - "pins.spiFrequency|block": "spi frequency %frequency", - "pins.spiMode|block": "spi mode %mode", - "pins.spiTransfer|block": "spi transfer %command into %response", - "pins.spiWrite|block": "spi write %value", - "pins|block": "pins", - "{id:category}ConfigStorage": "ConfigStorage", - "{id:category}Control": "Control", - "{id:category}Light": "Light", - "{id:category}Pins": "Pins", - "{id:category}SPI": "SPI", - "{id:group}Servo": "Servo" -} \ No newline at end of file diff --git a/libs/core---nrf52832/dal.d.ts b/libs/core---nrf52832/dal.d.ts deleted file mode 100755 index 62dffc91..00000000 --- a/libs/core---nrf52832/dal.d.ts +++ /dev/null @@ -1,1128 +0,0 @@ -// Auto-generated. Do not edit. -declare const enum DAL { - // /libraries/codal-core/inc/JACDAC/JACDAC.h - JD_VERSION = 5, - JD_SERIAL_MAX_BUFFERS = 10, - JD_SERIAL_RECEIVING = 2, - JD_SERIAL_TRANSMITTING = 4, - JD_SERIAL_TX_DRAIN_ENABLE = 8, - JD_SERIAL_BUS_RISE = 16, - JD_SERIAL_EVT_DATA_READY = 1, - JD_SERIAL_EVT_BUS_ERROR = 2, - JD_SERIAL_EVT_DRAIN = 3, - JD_SERIAL_EVT_RX_TIMEOUT = 4, - JD_SERIAL_EVT_BUS_CONNECTED = 5, - JD_SERIAL_EVT_BUS_DISCONNECTED = 6, - JD_SERIAL_HEADER_SIZE = 4, - JD_SERIAL_DATA_SIZE = 32, - JD_SERIAL_PACKET_SIZE = 36, - JD_SERIAL_MAXIMUM_BUFFERS = 10, - JD_SERIAL_DMA_TIMEOUT = 2, - JD_SERIAL_MAX_BAUD = 1000000, - JD_SERIAL_TX_MAX_BACKOFF = 4000, - JD_SERIAL_TX_MIN_BACKOFF = 1000, - Receiving = 0, - Transmitting = 1, - High = 2, - Low = 3, - Baud1M = 1, - Baud500K = 2, - Baud250K = 4, - Baud125K = 8, - // /libraries/codal-core/inc/JACDAC/JDAccelerometerDriver.h - JD_ACCEL_EVT_SEND_DATA = 1, - // /libraries/codal-core/inc/JACDAC/JDBridgeDriver.h - JD_BRIDGE_HISTORY_SIZE = 8, - // /libraries/codal-core/inc/JACDAC/JDClasses.h - STATIC_CLASS_START = 0, - STATIC_CLASS_END = 16777215, - DYNAMIC_CLASS_END = 4294967295, - JD_DRIVER_CLASS_CODAL_START = 0, - JD_DRIVER_CLASS_CODAL_END = 2000, - JD_DRIVER_CLASS_MAKECODE_START = 2000, - JD_DRIVER_CLASS_MAKECODE_END = 4000, - JD_DRIVER_CLASS_CONTROL = 0, - JD_DRIVER_CLASS_JOYSTICK = 1, - JD_DRIVER_CLASS_MESSAGE_BUS = 2, - JD_DRIVER_CLASS_BRIDGE = 3, - JD_DRIVER_CLASS_BUTTON = 4, - JD_DRIVER_CLASS_PIN = 5, - JD_DRIVER_CLASS_RELIABILITY_TESTER = 6, - JD_DRIVER_CLASS_ACCELEROMETER = 7, - JD_DRIVER_CLASS_CAPTOUCH_BUTTON = 8, - // /libraries/codal-core/inc/JACDAC/JDMessageBusDriver.h - JD_MESSAGEBUS_TYPE_EVENT = 1, - JD_MESSAGEBUS_TYPE_LISTEN = 2, - // /libraries/codal-core/inc/JACDAC/JDPinDriver.h - SetDigital = 0, - SetAnalog = 1, - SetServo = 2, - // /libraries/codal-core/inc/JACDAC/JDProtocol.h - JD_DRIVER_EVT_CONNECTED = 65520, - JD_DRIVER_EVT_DISCONNECTED = 65521, - JD_DRIVER_EVT_PAIRED = 65522, - JD_DRIVER_EVT_UNPAIRED = 65523, - JD_DRIVER_EVT_PAIR_REJECTED = 65524, - JD_DRIVER_EVT_PAIRING_RESPONSE = 65525, - JD_DRIVER_EVT_ERROR = 65526, - JD_DEVICE_FLAGS_LOCAL = 32768, - JD_DEVICE_FLAGS_REMOTE = 16384, - JD_DEVICE_FLAGS_BROADCAST = 8192, - JD_DEVICE_FLAGS_PAIR = 4096, - JD_DEVICE_DRIVER_MODE_MSK = 61440, - JD_DEVICE_FLAGS_PAIRABLE = 2048, - JD_DEVICE_FLAGS_PAIRED = 1024, - JD_DEVICE_FLAGS_PAIRING = 512, - JD_DEVICE_FLAGS_INITIALISED = 128, - JD_DEVICE_FLAGS_INITIALISING = 64, - JD_DEVICE_FLAGS_CP_SEEN = 32, - JD_DEVICE_ERROR_MSK = 15, - JD_LOGIC_DRIVER_MAX_FILTERS = 20, - JD_LOGIC_DRIVER_TIMEOUT = 254, - JD_LOGIC_ADDRESS_ALLOC_TIME = 254, - JD_LOGIC_DRIVER_CTRLPACKET_TIME = 112, - JD_LOGIC_DRIVER_EVT_CHANGED = 2, - CONTROL_JD_FLAGS_RESERVED = 32768, - CONTROL_JD_FLAGS_PAIRING_MODE = 16384, - CONTROL_JD_FLAGS_PAIRABLE = 8192, - CONTROL_JD_FLAGS_PAIRED = 4096, - CONTROL_JD_FLAGS_CONFLICT = 2048, - CONTROL_JD_FLAGS_UNCERTAIN = 1024, - CONTROL_JD_FLAGS_NACK = 512, - CONTROL_JD_FLAGS_ACK = 256, - CONTROL_JD_TYPE_HELLO = 1, - CONTROL_JD_TYPE_PAIRING_REQUEST = 2, - CONTROL_JD_TYPE_ERROR = 3, - CONTROL_JD_TYPE_PANIC = 255, - JD_PROTOCOL_EVT_SEND_CONTROL = 1, - JD_PROTOCOL_DRIVER_ARRAY_SIZE = 20, - CONTROL_PACKET_ERROR_NAME_LENGTH = 6, - VirtualDriver = 16384, - PairedDriver = 12288, - HostDriver = 32768, - PairableHostDriver = 34816, - BroadcastDriver = 40960, - SnifferDriver = 24576, - DRIVER_OK = 0, - DRIVER_CALIBRATION_IN_PROGRESS = 1, - DRIVER_CALIBRATION_REQUIRED = 2, - DRIVER_NO_RESOURCES = 3, - DRIVER_BUSY = 4, - DRIVER_COMMS_ERROR = 5, - DRIVER_INVALID_STATE = 6, - DRIVER_PERIPHERAL_MALFUNCTION = 7, - // /libraries/codal-core/inc/JACDAC/JDReliabilityTester.h - RELIABILITY_TEST_FINISHED = 7, - RELIABILITY_STATUS_TEST_IN_PROGRESS = 2, - RELIABILITY_STATUS_TEST_READY = 4, - RELIABILITY_STATUS_TEST_FINISHED = 8, - // /libraries/codal-core/inc/core/CodalComponent.h - DEVICE_ID_BUTTON_A = 1, - DEVICE_ID_BUTTON_B = 2, - DEVICE_ID_BUTTON_AB = 3, - DEVICE_ID_BUTTON_RESET = 4, - DEVICE_ID_ACCELEROMETER = 5, - DEVICE_ID_COMPASS = 6, - DEVICE_ID_DISPLAY = 7, - DEVICE_ID_THERMOMETER = 8, - DEVICE_ID_RADIO = 9, - DEVICE_ID_RADIO_DATA_READY = 10, - DEVICE_ID_MULTIBUTTON_ATTACH = 11, - DEVICE_ID_SERIAL = 12, - DEVICE_ID_GESTURE = 13, - DEVICE_ID_SYSTEM_TIMER = 14, - DEVICE_ID_SCHEDULER = 15, - DEVICE_ID_COMPONENT = 16, - DEVICE_ID_LIGHT_SENSOR = 17, - DEVICE_ID_TOUCH_SENSOR = 18, - DEVICE_ID_SYSTEM_DAC = 19, - DEVICE_ID_SYSTEM_MICROPHONE = 20, - DEVICE_ID_SYSTEM_LEVEL_DETECTOR = 21, - DEVICE_ID_SYSTEM_LEVEL_DETECTOR_SPL = 22, - DEVICE_ID_MSC = 23, - DEVICE_ID_SPI = 24, - DEVICE_ID_DISTANCE = 25, - DEVICE_ID_GYROSCOPE = 26, - DEVICE_ID_HUMIDITY = 27, - DEVICE_ID_PRESSURE = 28, - DEVICE_ID_JACDAC0 = 29, - DEVICE_ID_JACDAC1 = 30, - DEVICE_ID_JACDAC_PROTOCOL = 31, - DEVICE_ID_JACKROUTER = 32, - DEVICE_ID_GAME_ENGINE = 33, - DEVICE_ID_GAME_STATE_MANAGER = 34, - DEVICE_ID_SPRITE = 35, - DEVICE_ID_SINGLE_WIRE_SERIAL = 36, - DEVICE_ID_IO_P0 = 100, - DEVICE_ID_MESSAGE_BUS_LISTENER = 1021, - DEVICE_ID_NOTIFY_ONE = 1022, - DEVICE_ID_NOTIFY = 1023, - DEVICE_ID_BUTTON_UP = 2000, - DEVICE_ID_BUTTON_DOWN = 2001, - DEVICE_ID_BUTTON_LEFT = 2002, - DEVICE_ID_BUTTON_RIGHT = 2003, - DEVICE_ID_JD_DYNAMIC_ID = 3000, - DEVICE_COMPONENT_RUNNING = 4096, - DEVICE_COMPONENT_STATUS_SYSTEM_TICK = 8192, - DEVICE_COMPONENT_STATUS_IDLE_TICK = 16384, - DEVICE_COMPONENT_LISTENERS_CONFIGURED = 1, - DEVICE_COMPONENT_EVT_SYSTEM_TICK = 1, - // /libraries/codal-core/inc/core/CodalFiber.h - DEVICE_SCHEDULER_RUNNING = 1, - DEVICE_SCHEDULER_IDLE = 2, - DEVICE_FIBER_FLAG_FOB = 1, - DEVICE_FIBER_FLAG_PARENT = 2, - DEVICE_FIBER_FLAG_CHILD = 4, - DEVICE_FIBER_FLAG_DO_NOT_PAGE = 8, - DEVICE_SCHEDULER_EVT_TICK = 1, - DEVICE_SCHEDULER_EVT_IDLE = 2, - // /libraries/codal-core/inc/core/CodalListener.h - MESSAGE_BUS_LISTENER_PARAMETERISED = 1, - MESSAGE_BUS_LISTENER_METHOD = 2, - MESSAGE_BUS_LISTENER_BUSY = 4, - MESSAGE_BUS_LISTENER_REENTRANT = 8, - MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY = 16, - MESSAGE_BUS_LISTENER_DROP_IF_BUSY = 32, - MESSAGE_BUS_LISTENER_NONBLOCKING = 64, - MESSAGE_BUS_LISTENER_URGENT = 128, - MESSAGE_BUS_LISTENER_DELETING = 32768, - MESSAGE_BUS_LISTENER_IMMEDIATE = 192, - // /libraries/codal-core/inc/core/ErrorNo.h - DEVICE_OK = 0, - DEVICE_INVALID_PARAMETER = -1001, - DEVICE_NOT_SUPPORTED = -1002, - DEVICE_CALIBRATION_IN_PROGRESS = -1003, - DEVICE_CALIBRATION_REQUIRED = -1004, - DEVICE_NO_RESOURCES = -1005, - DEVICE_BUSY = -1006, - DEVICE_CANCELLED = -1007, - DEVICE_I2C_ERROR = -1010, - DEVICE_SERIAL_IN_USE = -1011, - DEVICE_NO_DATA = -1012, - DEVICE_NOT_IMPLEMENTED = -1013, - DEVICE_SPI_ERROR = -1014, - DEVICE_INVALID_STATE = -1015, - DEVICE_OOM = 20, - DEVICE_HEAP_ERROR = 30, - DEVICE_NULL_DEREFERENCE = 40, - DEVICE_USB_ERROR = 50, - DEVICE_HARDWARE_CONFIGURATION_ERROR = 90, - // /libraries/codal-core/inc/core/NotifyEvents.h - DISPLAY_EVT_FREE = 1, - CODAL_SERIAL_EVT_TX_EMPTY = 2, - BLE_EVT_SERIAL_TX_EMPTY = 3, - ARCADE_PLAYER_JOIN_RESULT = 4, - DEVICE_NOTIFY_USER_EVENT_BASE = 1024, - // /libraries/codal-core/inc/driver-models/AbstractButton.h - DEVICE_BUTTON_EVT_DOWN = 1, - DEVICE_BUTTON_EVT_UP = 2, - DEVICE_BUTTON_EVT_CLICK = 3, - DEVICE_BUTTON_EVT_LONG_CLICK = 4, - DEVICE_BUTTON_EVT_HOLD = 5, - DEVICE_BUTTON_EVT_DOUBLE_CLICK = 6, - DEVICE_BUTTON_LONG_CLICK_TIME = 1000, - DEVICE_BUTTON_HOLD_TIME = 1500, - DEVICE_BUTTON_STATE = 1, - DEVICE_BUTTON_STATE_HOLD_TRIGGERED = 2, - DEVICE_BUTTON_STATE_CLICK = 4, - DEVICE_BUTTON_STATE_LONG_CLICK = 8, - DEVICE_BUTTON_SIGMA_MIN = 0, - DEVICE_BUTTON_SIGMA_MAX = 12, - DEVICE_BUTTON_SIGMA_THRESH_HI = 8, - DEVICE_BUTTON_SIGMA_THRESH_LO = 2, - DEVICE_BUTTON_DOUBLE_CLICK_THRESH = 50, - DEVICE_BUTTON_SIMPLE_EVENTS = 0, - DEVICE_BUTTON_ALL_EVENTS = 1, - ACTIVE_LOW = 0, - ACTIVE_HIGH = 1, - // /libraries/codal-core/inc/driver-models/Accelerometer.h - ACCELEROMETER_IMU_DATA_VALID = 2, - ACCELEROMETER_EVT_DATA_UPDATE = 1, - ACCELEROMETER_EVT_NONE = 0, - ACCELEROMETER_EVT_TILT_UP = 1, - ACCELEROMETER_EVT_TILT_DOWN = 2, - ACCELEROMETER_EVT_TILT_LEFT = 3, - ACCELEROMETER_EVT_TILT_RIGHT = 4, - ACCELEROMETER_EVT_FACE_UP = 5, - ACCELEROMETER_EVT_FACE_DOWN = 6, - ACCELEROMETER_EVT_FREEFALL = 7, - ACCELEROMETER_EVT_3G = 8, - ACCELEROMETER_EVT_6G = 9, - ACCELEROMETER_EVT_8G = 10, - ACCELEROMETER_EVT_SHAKE = 11, - ACCELEROMETER_EVT_2G = 12, - ACCELEROMETER_REST_TOLERANCE = 200, - ACCELEROMETER_TILT_TOLERANCE = 200, - ACCELEROMETER_FREEFALL_TOLERANCE = 400, - ACCELEROMETER_SHAKE_TOLERANCE = 400, - ACCELEROMETER_2G_TOLERANCE = 2048, - ACCELEROMETER_3G_TOLERANCE = 3072, - ACCELEROMETER_6G_TOLERANCE = 6144, - ACCELEROMETER_8G_TOLERANCE = 8192, - ACCELEROMETER_GESTURE_DAMPING = 5, - ACCELEROMETER_SHAKE_DAMPING = 10, - ACCELEROMETER_SHAKE_RTX = 30, - ACCELEROMETER_SHAKE_COUNT_THRESHOLD = 4, - // /libraries/codal-core/inc/driver-models/Compass.h - COMPASS_STATUS_RUNNING = 1, - COMPASS_STATUS_CALIBRATED = 2, - COMPASS_STATUS_CALIBRATING = 4, - COMPASS_STATUS_ADDED_TO_IDLE = 8, - COMPASS_EVT_DATA_UPDATE = 1, - COMPASS_EVT_CONFIG_NEEDED = 2, - COMPASS_EVT_CALIBRATE = 3, - COMPASS_EVT_CALIBRATION_NEEDED = 4, - // /libraries/codal-core/inc/driver-models/Gyroscope.h - GYROSCOPE_IMU_DATA_VALID = 2, - GYROSCOPE_EVT_DATA_UPDATE = 1, - // /libraries/codal-core/inc/driver-models/LowLevelTimer.h - TimerModeTimer = 0, - TimerModeCounter = 1, - TimerModeAlternateFunction = 2, - BitMode8 = 0, - BitMode16 = 1, - BitMode24 = 2, - BitMode32 = 3, - // /libraries/codal-core/inc/driver-models/Pin.h - IO_STATUS_DIGITAL_IN = 1, - IO_STATUS_DIGITAL_OUT = 2, - IO_STATUS_ANALOG_IN = 4, - IO_STATUS_ANALOG_OUT = 8, - IO_STATUS_TOUCH_IN = 16, - IO_STATUS_EVENT_ON_EDGE = 32, - IO_STATUS_EVENT_PULSE_ON_EDGE = 64, - DEVICE_PIN_MAX_OUTPUT = 1023, - DEVICE_PIN_MAX_SERVO_RANGE = 180, - DEVICE_PIN_DEFAULT_SERVO_RANGE = 2000, - DEVICE_PIN_DEFAULT_SERVO_CENTER = 1500, - DEVICE_PIN_EVENT_NONE = 0, - DEVICE_PIN_EVENT_ON_EDGE = 1, - DEVICE_PIN_EVENT_ON_PULSE = 2, - DEVICE_PIN_EVENT_ON_TOUCH = 3, - DEVICE_PIN_EVT_RISE = 2, - DEVICE_PIN_EVT_FALL = 3, - DEVICE_PIN_EVT_PULSE_HI = 4, - DEVICE_PIN_EVT_PULSE_LO = 5, - PIN_CAPABILITY_DIGITAL = 1, - PIN_CAPABILITY_ANALOG = 2, - PIN_CAPABILITY_AD = 3, - PIN_CAPABILITY_ALL = 3, - None = 0, - Down = 1, - Up = 2, - // /libraries/codal-core/inc/driver-models/Radio.h - RADIO_EVT_DATA_READY = 2, - // /libraries/codal-core/inc/driver-models/SPIFlash.h - SPIFLASH_PAGE_SIZE = 256, - SPIFLASH_SMALL_ROW_PAGES = 16, - SPIFLASH_BIG_ROW_PAGES = 256, - // /libraries/codal-core/inc/driver-models/Sensor.h - SENSOR_THRESHOLD_LOW = 1, - SENSOR_THRESHOLD_HIGH = 2, - SENSOR_UPDATE_NEEDED = 3, - SENSOR_INITIALISED = 1, - SENSOR_HIGH_THRESHOLD_PASSED = 2, - SENSOR_LOW_THRESHOLD_PASSED = 4, - SENSOR_LOW_THRESHOLD_ENABLED = 8, - SENSOR_HIGH_THRESHOLD_ENABLED = 16, - SENSOR_DEFAULT_SENSITIVITY = 868, - SENSOR_DEFAULT_SAMPLE_PERIOD = 500, - // /libraries/codal-core/inc/driver-models/Serial.h - CODAL_SERIAL_DEFAULT_BAUD_RATE = 115200, - CODAL_SERIAL_DEFAULT_BUFFER_SIZE = 20, - CODAL_SERIAL_EVT_DELIM_MATCH = 1, - CODAL_SERIAL_EVT_HEAD_MATCH = 2, - CODAL_SERIAL_EVT_RX_FULL = 3, - CODAL_SERIAL_EVT_DATA_RECEIVED = 4, - CODAL_SERIAL_STATUS_RX_IN_USE = 1, - CODAL_SERIAL_STATUS_TX_IN_USE = 2, - CODAL_SERIAL_STATUS_RX_BUFF_INIT = 4, - CODAL_SERIAL_STATUS_TX_BUFF_INIT = 8, - CODAL_SERIAL_STATUS_RXD = 16, - ASYNC = 0, - SYNC_SPINWAIT = 1, - SYNC_SLEEP = 2, - RxInterrupt = 0, - TxInterrupt = 1, - // /libraries/codal-core/inc/driver-models/SingleWireSerial.h - SWS_EVT_DATA_RECEIVED = 1, - SWS_EVT_DATA_SENT = 2, - SWS_EVT_ERROR = 3, - SWS_EVT_DATA_DROPPED = 4, - SingleWireRx = 0, - SingleWireTx = 1, - SingleWireDisconnected = 2, - // /libraries/codal-core/inc/driver-models/Timer.h - CODAL_TIMER_DEFAULT_EVENT_LIST_SIZE = 10, - // /libraries/codal-core/inc/drivers/AnalogSensor.h - ANALOG_THRESHOLD_LOW = 1, - ANALOG_THRESHOLD_HIGH = 2, - ANALOG_SENSOR_UPDATE_NEEDED = 3, - ANALOG_SENSOR_INITIALISED = 1, - ANALOG_SENSOR_HIGH_THRESHOLD_PASSED = 2, - ANALOG_SENSOR_LOW_THRESHOLD_PASSED = 4, - ANALOG_SENSOR_LOW_THRESHOLD_ENABLED = 8, - ANALOG_SENSOR_HIGH_THRESHOLD_ENABLED = 16, - // /libraries/codal-core/inc/drivers/AnimatedDisplay.h - DISPLAY_EVT_ANIMATION_COMPLETE = 1, - DISPLAY_DEFAULT_AUTOCLEAR = 1, - DISPLAY_SPACING = 1, - DISPLAY_ANIMATE_DEFAULT_POS = -255, - DISPLAY_DEFAULT_SCROLL_SPEED = 120, - DISPLAY_DEFAULT_SCROLL_STRIDE = -1, - DISPLAY_DEFAULT_PRINT_SPEED = 400, - ANIMATION_MODE_NONE = 0, - ANIMATION_MODE_STOPPED = 1, - ANIMATION_MODE_SCROLL_TEXT = 2, - ANIMATION_MODE_PRINT_TEXT = 3, - ANIMATION_MODE_SCROLL_IMAGE = 4, - ANIMATION_MODE_ANIMATE_IMAGE = 5, - ANIMATION_MODE_ANIMATE_IMAGE_WITH_CLEAR = 6, - ANIMATION_MODE_PRINT_CHARACTER = 7, - // /libraries/codal-core/inc/drivers/FAT.h - FAT_RESERVED_SECTORS = 1, - FAT_ROOT_DIR_SECTORS = 4, - // /libraries/codal-core/inc/drivers/HID.h - HID_REQUEST_GET_REPORT = 1, - HID_REQUEST_GET_IDLE = 2, - HID_REQUEST_GET_PROTOCOL = 3, - HID_REQUEST_SET_REPORT = 9, - HID_REQUEST_SET_IDLE = 10, - HID_REQUEST_SET_PROTOCOL = 11, - // /libraries/codal-core/inc/drivers/HIDKeyboard.h - HID_KEYBOARD_NUM_REPORTS = 3, - HID_KEYBOARD_REPORT_GENERIC = 1, - HID_KEYBOARD_REPORT_CONSUMER = 2, - HID_KEYBOARD_KEYSTATE_SIZE_GENERIC = 8, - HID_KEYBOARD_KEYSTATE_SIZE_CONSUMER = 2, - HID_KEYBOARD_MODIFIER_OFFSET = 2, - HID_KEYBOARD_DELAY_DEFAULT = 10, - PressKey = 0, - ReleaseKey = 1, - // /libraries/codal-core/inc/drivers/JackRouter.h - AllDown = 1, - HeadPhones = 2, - Buzzer = 3, - BuzzerAndSerial = 4, - // /libraries/codal-core/inc/drivers/KeyMap.h - KEYMAP_ALL_KEYS_UP_Val = 1, - KEYMAP_ALL_KEYS_UP_POS = 28, - KEYMAP_NORMAL_KEY_Val = 0, - KEYMAP_MODIFIER_KEY_Val = 1, - KEYMAP_MODIFIER_POS = 29, - KEYMAP_MEDIA_KEY_Val = 1, - KEYMAP_MEDIA_POS = 30, - KEYMAP_KEY_UP_Val = 0, - KEYMAP_KEY_DOWN_Val = 1, - KEYMAP_KEY_DOWN_POS = 31, - // /libraries/codal-core/inc/drivers/LEDMatrix.h - LED_MATRIX_GREYSCALE_BIT_DEPTH = 8, - LED_MATRIX_EVT_LIGHT_SENSE = 2, - LED_MATRIX_EVT_FRAME_TIMEOUT = 3, - LED_MATRIX_MINIMUM_BRIGHTNESS = 1, - LED_MATRIX_MAXIMUM_BRIGHTNESS = 255, - LED_MATRIX_DEFAULT_BRIGHTNESS = 255, - DISPLAY_MODE_BLACK_AND_WHITE = 0, - DISPLAY_MODE_GREYSCALE = 1, - DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE = 2, - MATRIX_DISPLAY_ROTATION_0 = 0, - MATRIX_DISPLAY_ROTATION_90 = 1, - MATRIX_DISPLAY_ROTATION_180 = 2, - MATRIX_DISPLAY_ROTATION_270 = 3, - NO_CONN = 0, - // /libraries/codal-core/inc/drivers/MAG3110.h - MAG3110_DEFAULT_ADDR = 29, - MAG_DR_STATUS = 0, - MAG_OUT_X_MSB = 1, - MAG_OUT_X_LSB = 2, - MAG_OUT_Y_MSB = 3, - MAG_OUT_Y_LSB = 4, - MAG_OUT_Z_MSB = 5, - MAG_OUT_Z_LSB = 6, - MAG_WHOAMI = 7, - MAG_SYSMOD = 8, - MAG_OFF_X_MSB = 9, - MAG_OFF_X_LSB = 10, - MAG_OFF_Y_MSB = 11, - MAG_OFF_Y_LSB = 12, - MAG_OFF_Z_MSB = 13, - MAG_OFF_Z_LSB = 14, - MAG_DIE_TEMP = 15, - MAG_CTRL_REG1 = 16, - MAG_CTRL_REG2 = 17, - MAG3110_SAMPLE_RATES = 11, - MAG3110_WHOAMI_VAL = 196, - // /libraries/codal-core/inc/drivers/MMA8453.h - MMA8453_DEFAULT_ADDR = 56, - MMA8453_WHOAMI_VAL = 58, - // /libraries/codal-core/inc/drivers/MMA8653.h - MICROBIT_ACCEL_PITCH_ROLL_VALID = 2, - MICROBIT_ACCEL_ADDED_TO_IDLE = 4, - MMA8653_DEFAULT_ADDR = 58, - MMA8653_STATUS = 0, - MMA8653_OUT_X_MSB = 1, - MMA8653_WHOAMI = 13, - MMA8653_XYZ_DATA_CFG = 14, - MMA8653_CTRL_REG1 = 42, - MMA8653_CTRL_REG2 = 43, - MMA8653_CTRL_REG3 = 44, - MMA8653_CTRL_REG4 = 45, - MMA8653_CTRL_REG5 = 46, - MMA8653_WHOAMI_VAL = 90, - MMA8653_SAMPLE_RANGES = 3, - MMA8653_SAMPLE_RATES = 8, - // /libraries/codal-core/inc/drivers/MPU6050.h - MPU6050_DEFAULT_ADDR = 104, - MPU6050_WHOAMI = 117, - MPU6050_WHOAMI_VAL = 52, - // /libraries/codal-core/inc/drivers/MultiButton.h - MULTI_BUTTON_STATE_1 = 1, - MULTI_BUTTON_STATE_2 = 2, - MULTI_BUTTON_HOLD_TRIGGERED_1 = 4, - MULTI_BUTTON_HOLD_TRIGGERED_2 = 8, - MULTI_BUTTON_SUPRESSED_1 = 16, - MULTI_BUTTON_SUPRESSED_2 = 32, - MULTI_BUTTON_ATTACHED = 64, - // /libraries/codal-core/inc/drivers/ST7735.h - MADCTL_MY = 128, - MADCTL_MX = 64, - MADCTL_MV = 32, - MADCTL_ML = 16, - MADCTL_RGB = 0, - MADCTL_BGR = 8, - MADCTL_MH = 4, - // /libraries/codal-core/inc/drivers/TouchButton.h - TOUCH_BUTTON_CALIBRATION_PERIOD = 10, - TOUCH_BUTTON_CALIBRATION_LINEAR_OFFSET = 2, - TOUCH_BUTTON_CALIBRATION_PERCENTAGE_OFFSET = 5, - TOUCH_BUTTON_CALIBRATING = 16, - // /libraries/codal-core/inc/drivers/TouchSensor.h - TOUCH_SENSOR_MAX_BUTTONS = 10, - TOUCH_SENSOR_SAMPLE_PERIOD = 50, - TOUCH_SENSE_SAMPLE_MAX = 1000, - TOUCH_SENSOR_UPDATE_NEEDED = 1, - // /libraries/codal-core/inc/drivers/USB_HID_Keys.h - KEY_MOD_LCTRL = 1, - KEY_MOD_LSHIFT = 2, - KEY_MOD_LALT = 4, - KEY_MOD_LMETA = 8, - KEY_MOD_RCTRL = 16, - KEY_MOD_RSHIFT = 32, - KEY_MOD_RALT = 64, - KEY_MOD_RMETA = 128, - KEY_NONE = 0, - KEY_ERR_OVF = 1, - KEY_A = 4, - KEY_B = 5, - KEY_C = 6, - KEY_D = 7, - KEY_E = 8, - KEY_F = 9, - KEY_G = 10, - KEY_H = 11, - KEY_I = 12, - KEY_J = 13, - KEY_K = 14, - KEY_L = 15, - KEY_M = 16, - KEY_N = 17, - KEY_O = 18, - KEY_P = 19, - KEY_Q = 20, - KEY_R = 21, - KEY_S = 22, - KEY_T = 23, - KEY_U = 24, - KEY_V = 25, - KEY_W = 26, - KEY_X = 27, - KEY_Y = 28, - KEY_Z = 29, - KEY_1 = 30, - KEY_2 = 31, - KEY_3 = 32, - KEY_4 = 33, - KEY_5 = 34, - KEY_6 = 35, - KEY_7 = 36, - KEY_8 = 37, - KEY_9 = 38, - KEY_0 = 39, - KEY_ENTER = 40, - KEY_ESC = 41, - KEY_BACKSPACE = 42, - KEY_TAB = 43, - KEY_SPACE = 44, - KEY_MINUS = 45, - KEY_EQUAL = 46, - KEY_LEFTBRACE = 47, - KEY_RIGHTBRACE = 48, - KEY_BACKSLASH = 49, - KEY_HASHTILDE = 50, - KEY_SEMICOLON = 51, - KEY_APOSTROPHE = 52, - KEY_GRAVE = 53, - KEY_COMMA = 54, - KEY_DOT = 55, - KEY_SLASH = 56, - KEY_CAPSLOCK = 57, - KEY_F1 = 58, - KEY_F2 = 59, - KEY_F3 = 60, - KEY_F4 = 61, - KEY_F5 = 62, - KEY_F6 = 63, - KEY_F7 = 64, - KEY_F8 = 65, - KEY_F9 = 66, - KEY_F10 = 67, - KEY_F11 = 68, - KEY_F12 = 69, - KEY_SYSRQ = 70, - KEY_SCROLLLOCK = 71, - KEY_PAUSE = 72, - KEY_INSERT = 73, - KEY_HOME = 74, - KEY_PAGEUP = 75, - KEY_DELETE = 76, - KEY_END = 77, - KEY_PAGEDOWN = 78, - KEY_RIGHT = 79, - KEY_LEFT = 80, - KEY_DOWN = 81, - KEY_UP = 82, - KEY_NUMLOCK = 83, - KEY_KPSLASH = 84, - KEY_KPASTERISK = 85, - KEY_KPMINUS = 86, - KEY_KPPLUS = 87, - KEY_KPENTER = 88, - KEY_KP1 = 89, - KEY_KP2 = 90, - KEY_KP3 = 91, - KEY_KP4 = 92, - KEY_KP5 = 93, - KEY_KP6 = 94, - KEY_KP7 = 95, - KEY_KP8 = 96, - KEY_KP9 = 97, - KEY_KP0 = 98, - KEY_KPDOT = 99, - KEY_102ND = 100, - KEY_COMPOSE = 101, - KEY_POWER = 102, - KEY_KPEQUAL = 103, - KEY_F13 = 104, - KEY_F14 = 105, - KEY_F15 = 106, - KEY_F16 = 107, - KEY_F17 = 108, - KEY_F18 = 109, - KEY_F19 = 110, - KEY_F20 = 111, - KEY_F21 = 112, - KEY_F22 = 113, - KEY_F23 = 114, - KEY_F24 = 115, - KEY_OPEN = 116, - KEY_HELP = 117, - KEY_PROPS = 118, - KEY_FRONT = 119, - KEY_STOP = 120, - KEY_AGAIN = 121, - KEY_UNDO = 122, - KEY_CUT = 123, - KEY_COPY = 124, - KEY_PASTE = 125, - KEY_FIND = 126, - KEY_MUTE = 127, - KEY_VOLUMEUP = 128, - KEY_VOLUMEDOWN = 129, - KEY_KPCOMMA = 133, - KEY_RO = 135, - KEY_KATAKANAHIRAGANA = 136, - KEY_YEN = 137, - KEY_HENKAN = 138, - KEY_MUHENKAN = 139, - KEY_KPJPCOMMA = 140, - KEY_HANGEUL = 144, - KEY_HANJA = 145, - KEY_KATAKANA = 146, - KEY_HIRAGANA = 147, - KEY_ZENKAKUHANKAKU = 148, - KEY_KPLEFTPAREN = 182, - KEY_KPRIGHTPAREN = 183, - KEY_LEFTCTRL = 224, - KEY_LEFTSHIFT = 225, - KEY_LEFTALT = 226, - KEY_LEFTMETA = 227, - KEY_RIGHTCTRL = 228, - KEY_RIGHTSHIFT = 229, - KEY_RIGHTALT = 230, - KEY_RIGHTMETA = 231, - KEY_MEDIA_PLAYPAUSE = 232, - KEY_MEDIA_STOPCD = 233, - KEY_MEDIA_PREVIOUSSONG = 234, - KEY_MEDIA_NEXTSONG = 235, - KEY_MEDIA_EJECTCD = 236, - KEY_MEDIA_VOLUMEUP = 237, - KEY_MEDIA_VOLUMEDOWN = 238, - KEY_MEDIA_MUTE = 239, - KEY_MEDIA_WWW = 240, - KEY_MEDIA_BACK = 241, - KEY_MEDIA_FORWARD = 242, - KEY_MEDIA_STOP = 243, - KEY_MEDIA_FIND = 244, - KEY_MEDIA_SCROLLUP = 245, - KEY_MEDIA_SCROLLDOWN = 246, - KEY_MEDIA_EDIT = 247, - KEY_MEDIA_SLEEP = 248, - KEY_MEDIA_COFFEE = 249, - KEY_MEDIA_REFRESH = 250, - KEY_MEDIA_CALC = 251, - // /libraries/codal-core/inc/drivers/uf2format.h - UF2FORMAT_H = 1, - APP_START_ADDRESS = 8192, - UF2_FLAG_NOFLASH = 1, - // /libraries/codal-core/inc/streams/DataStream.h - DATASTREAM_MAXIMUM_BUFFERS = 1, - // /libraries/codal-core/inc/streams/LevelDetector.h - LEVEL_THRESHOLD_LOW = 1, - LEVEL_THRESHOLD_HIGH = 2, - LEVEL_DETECTOR_INITIALISED = 1, - LEVEL_DETECTOR_HIGH_THRESHOLD_PASSED = 2, - LEVEL_DETECTOR_LOW_THRESHOLD_PASSED = 4, - LEVEL_DETECTOR_DEFAULT_WINDOW_SIZE = 128, - // /libraries/codal-core/inc/streams/LevelDetectorSPL.h - LEVEL_DETECTOR_SPL_INITIALISED = 1, - LEVEL_DETECTOR_SPL_HIGH_THRESHOLD_PASSED = 2, - LEVEL_DETECTOR_SPL_LOW_THRESHOLD_PASSED = 4, - LEVEL_DETECTOR_SPL_DEFAULT_WINDOW_SIZE = 128, - // /libraries/codal-core/inc/streams/Synthesizer.h - SYNTHESIZER_SAMPLE_RATE = 44100, - TONE_WIDTH = 1024, - // /libraries/codal-core/inc/types/BitmapFont.h - BITMAP_FONT_WIDTH = 5, - BITMAP_FONT_HEIGHT = 5, - BITMAP_FONT_ASCII_START = 32, - BITMAP_FONT_ASCII_END = 126, - // /libraries/codal-core/inc/types/CoordinateSystem.h - COORDINATE_SPACE_ROTATED_0 = 0, - COORDINATE_SPACE_ROTATED_90 = 1, - COORDINATE_SPACE_ROTATED_180 = 2, - COORDINATE_SPACE_ROTATED_270 = 3, - RAW = 0, - SIMPLE_CARTESIAN = 1, - NORTH_EAST_DOWN = 2, - NORTH_EAST_UP = 3, - // /libraries/codal-core/inc/types/Event.h - DEVICE_ID_ANY = 0, - DEVICE_EVT_ANY = 0, - CREATE_ONLY = 0, - CREATE_AND_FIRE = 1, - DEVICE_EVENT_DEFAULT_LAUNCH_MODE = 1, - // /libraries/codal-core/inc/types/RefCounted.h - REF_TAG_STRING = 1, - REF_TAG_BUFFER = 2, - REF_TAG_IMAGE = 3, - REF_TAG_USER = 32, - // /pxtapp/configkeys.h - CFG_PIN_NAME_MSK = 65535, - CFG_PIN_CONFIG_MSK = 4294901760, - CFG_PIN_CONFIG_ACTIVE_LO = 65536, - CFG_MAGIC0 = 513675505, - CFG_MAGIC1 = 539130489, - CFG_PIN_ACCELEROMETER_INT = 1, - CFG_PIN_ACCELEROMETER_SCL = 2, - CFG_PIN_ACCELEROMETER_SDA = 3, - CFG_PIN_BTN_A = 4, - CFG_PIN_BTN_B = 5, - CFG_PIN_BTN_SLIDE = 6, - CFG_PIN_DOTSTAR_CLOCK = 7, - CFG_PIN_DOTSTAR_DATA = 8, - CFG_PIN_FLASH_CS = 9, - CFG_PIN_FLASH_MISO = 10, - CFG_PIN_FLASH_MOSI = 11, - CFG_PIN_FLASH_SCK = 12, - CFG_PIN_LED = 13, - CFG_PIN_LIGHT = 14, - CFG_PIN_MICROPHONE = 15, - CFG_PIN_MIC_CLOCK = 16, - CFG_PIN_MIC_DATA = 17, - CFG_PIN_MISO = 18, - CFG_PIN_MOSI = 19, - CFG_PIN_NEOPIXEL = 20, - CFG_PIN_RX = 21, - CFG_PIN_RXLED = 22, - CFG_PIN_SCK = 23, - CFG_PIN_SCL = 24, - CFG_PIN_SDA = 25, - CFG_PIN_SPEAKER_AMP = 26, - CFG_PIN_TEMPERATURE = 27, - CFG_PIN_TX = 28, - CFG_PIN_TXLED = 29, - CFG_PIN_IR_OUT = 30, - CFG_PIN_IR_IN = 31, - CFG_PIN_DISPLAY_SCK = 32, - CFG_PIN_DISPLAY_MISO = 33, - CFG_PIN_DISPLAY_MOSI = 34, - CFG_PIN_DISPLAY_CS = 35, - CFG_PIN_DISPLAY_DC = 36, - CFG_DISPLAY_WIDTH = 37, - CFG_DISPLAY_HEIGHT = 38, - CFG_DISPLAY_CFG0 = 39, - CFG_DISPLAY_CFG1 = 40, - CFG_DISPLAY_CFG2 = 41, - CFG_DISPLAY_CFG3 = 42, - CFG_PIN_DISPLAY_RST = 43, - CFG_PIN_DISPLAY_BL = 44, - CFG_PIN_SERVO_1 = 45, - CFG_PIN_SERVO_2 = 46, - CFG_PIN_BTN_LEFT = 47, - CFG_PIN_BTN_RIGHT = 48, - CFG_PIN_BTN_UP = 49, - CFG_PIN_BTN_DOWN = 50, - CFG_PIN_BTN_MENU = 51, - CFG_PIN_LED_R = 52, - CFG_PIN_LED_G = 53, - CFG_PIN_LED_B = 54, - CFG_PIN_LED1 = 55, - CFG_PIN_LED2 = 56, - CFG_PIN_LED3 = 57, - CFG_PIN_LED4 = 58, - CFG_SPEAKER_VOLUME = 59, - CFG_PIN_JACK_TX = 60, - CFG_PIN_JACK_SENSE = 61, - CFG_PIN_JACK_HPEN = 62, - CFG_PIN_JACK_BZEN = 63, - CFG_PIN_JACK_PWREN = 64, - CFG_PIN_JACK_SND = 65, - CFG_PIN_JACK_BUSLED = 66, - CFG_PIN_JACK_COMMLED = 67, - CFG_PIN_BTN_SOFT_RESET = 69, - CFG_ACCELEROMETER_TYPE = 70, - CFG_PIN_BTNMX_LATCH = 71, - CFG_PIN_BTNMX_CLOCK = 72, - CFG_PIN_BTNMX_DATA = 73, - CFG_PIN_BTN_MENU2 = 74, - CFG_PIN_BATTSENSE = 75, - CFG_PIN_VIBRATION = 76, - CFG_PIN_PWREN = 77, - ACCELEROMETER_TYPE_LIS3DH = 50, - ACCELEROMETER_TYPE_MMA8453 = 56, - ACCELEROMETER_TYPE_FXOS8700 = 60, - ACCELEROMETER_TYPE_MMA8653 = 58, - ACCELEROMETER_TYPE_MSA300 = 76, - ACCELEROMETER_TYPE_MPU6050 = 104, - CFG_PIN_A0 = 100, - CFG_PIN_A1 = 101, - CFG_PIN_A2 = 102, - CFG_PIN_A3 = 103, - CFG_PIN_A4 = 104, - CFG_PIN_A5 = 105, - CFG_PIN_A6 = 106, - CFG_PIN_A7 = 107, - CFG_PIN_A8 = 108, - CFG_PIN_A9 = 109, - CFG_PIN_A10 = 110, - CFG_PIN_A11 = 111, - CFG_PIN_A12 = 112, - CFG_PIN_A13 = 113, - CFG_PIN_A14 = 114, - CFG_PIN_A15 = 115, - CFG_PIN_A16 = 116, - CFG_PIN_A17 = 117, - CFG_PIN_A18 = 118, - CFG_PIN_A19 = 119, - CFG_PIN_A20 = 120, - CFG_PIN_A21 = 121, - CFG_PIN_A22 = 122, - CFG_PIN_A23 = 123, - CFG_PIN_A24 = 124, - CFG_PIN_A25 = 125, - CFG_PIN_A26 = 126, - CFG_PIN_A27 = 127, - CFG_PIN_A28 = 128, - CFG_PIN_A29 = 129, - CFG_PIN_A30 = 130, - CFG_PIN_A31 = 131, - CFG_PIN_D0 = 150, - CFG_PIN_D1 = 151, - CFG_PIN_D2 = 152, - CFG_PIN_D3 = 153, - CFG_PIN_D4 = 154, - CFG_PIN_D5 = 155, - CFG_PIN_D6 = 156, - CFG_PIN_D7 = 157, - CFG_PIN_D8 = 158, - CFG_PIN_D9 = 159, - CFG_PIN_D10 = 160, - CFG_PIN_D11 = 161, - CFG_PIN_D12 = 162, - CFG_PIN_D13 = 163, - CFG_PIN_D14 = 164, - CFG_PIN_D15 = 165, - CFG_PIN_D16 = 166, - CFG_PIN_D17 = 167, - CFG_PIN_D18 = 168, - CFG_PIN_D19 = 169, - CFG_PIN_D20 = 170, - CFG_PIN_D21 = 171, - CFG_PIN_D22 = 172, - CFG_PIN_D23 = 173, - CFG_PIN_D24 = 174, - CFG_PIN_D25 = 175, - CFG_PIN_D26 = 176, - CFG_PIN_D27 = 177, - CFG_PIN_D28 = 178, - CFG_PIN_D29 = 179, - CFG_PIN_D30 = 180, - CFG_PIN_D31 = 181, - CFG_NUM_NEOPIXELS = 200, - CFG_NUM_DOTSTARS = 201, - CFG_DEFAULT_BUTTON_MODE = 202, - CFG_SWD_ENABLED = 203, - CFG_FLASH_BYTES = 204, - CFG_RAM_BYTES = 205, - CFG_SYSTEM_HEAP_BYTES = 206, - CFG_LOW_MEM_SIMULATION_KB = 207, - CFG_BOOTLOADER_BOARD_ID = 208, - CFG_UF2_FAMILY = 209, - CFG_PINS_PORT_SIZE = 210, - CFG_BOOTLOADER_PROTECTION = 211, - CFG_POWER_DEEPSLEEP_TIMEOUT = 212, - CFG_ANALOG_BUTTON_THRESHOLD = 213, - CFG_PIN_B0 = 300, - CFG_PIN_B1 = 301, - CFG_PIN_B2 = 302, - CFG_PIN_B3 = 303, - CFG_PIN_B4 = 304, - CFG_PIN_B5 = 305, - CFG_PIN_B6 = 306, - CFG_PIN_B7 = 307, - CFG_PIN_B8 = 308, - CFG_PIN_B9 = 309, - CFG_PIN_B10 = 310, - CFG_PIN_B11 = 311, - CFG_PIN_B12 = 312, - CFG_PIN_B13 = 313, - CFG_PIN_B14 = 314, - CFG_PIN_B15 = 315, - CFG_PIN_B16 = 316, - CFG_PIN_B17 = 317, - CFG_PIN_B18 = 318, - CFG_PIN_B19 = 319, - CFG_PIN_B20 = 320, - CFG_PIN_B21 = 321, - CFG_PIN_B22 = 322, - CFG_PIN_B23 = 323, - CFG_PIN_B24 = 324, - CFG_PIN_B25 = 325, - CFG_PIN_B26 = 326, - CFG_PIN_B27 = 327, - CFG_PIN_B28 = 328, - CFG_PIN_B29 = 329, - CFG_PIN_B30 = 330, - CFG_PIN_B31 = 331, - CFG_PIN_C0 = 350, - CFG_PIN_C1 = 351, - CFG_PIN_C2 = 352, - CFG_PIN_C3 = 353, - CFG_PIN_C4 = 354, - CFG_PIN_C5 = 355, - CFG_PIN_C6 = 356, - CFG_PIN_C7 = 357, - CFG_PIN_C8 = 358, - CFG_PIN_C9 = 359, - CFG_PIN_C10 = 360, - CFG_PIN_C11 = 361, - CFG_PIN_C12 = 362, - CFG_PIN_C13 = 363, - CFG_PIN_C14 = 364, - CFG_PIN_C15 = 365, - CFG_PIN_C16 = 366, - CFG_PIN_C17 = 367, - CFG_PIN_C18 = 368, - CFG_PIN_C19 = 369, - CFG_PIN_C20 = 370, - CFG_PIN_C21 = 371, - CFG_PIN_C22 = 372, - CFG_PIN_C23 = 373, - CFG_PIN_C24 = 374, - CFG_PIN_C25 = 375, - CFG_PIN_C26 = 376, - CFG_PIN_C27 = 377, - CFG_PIN_C28 = 378, - CFG_PIN_C29 = 379, - CFG_PIN_C30 = 380, - CFG_PIN_C31 = 381, - CFG_PIN_P0 = 400, - CFG_PIN_P1 = 401, - CFG_PIN_P2 = 402, - CFG_PIN_P3 = 403, - CFG_PIN_P4 = 404, - CFG_PIN_P5 = 405, - CFG_PIN_P6 = 406, - CFG_PIN_P7 = 407, - CFG_PIN_P8 = 408, - CFG_PIN_P9 = 409, - CFG_PIN_P10 = 410, - CFG_PIN_P11 = 411, - CFG_PIN_P12 = 412, - CFG_PIN_P13 = 413, - CFG_PIN_P14 = 414, - CFG_PIN_P15 = 415, - CFG_PIN_P16 = 416, - CFG_PIN_P17 = 417, - CFG_PIN_P18 = 418, - CFG_PIN_P19 = 419, - CFG_PIN_P20 = 420, - CFG_PIN_LORA_MISO = 1001, - CFG_PIN_LORA_MOSI = 1002, - CFG_PIN_LORA_SCK = 1003, - CFG_PIN_LORA_CS = 1004, - CFG_PIN_LORA_BOOT = 1005, - CFG_PIN_LORA_RESET = 1006, - CFG_PIN_IRRXLED = 1007, - CFG_PIN_IRTXLED = 1008, - CFG_PIN_LCD_RESET = 1009, - CFG_PIN_LCD_ENABLE = 1010, - CFG_PIN_LCD_DATALINE4 = 1011, - CFG_PIN_LCD_DATALINE5 = 1012, - CFG_PIN_LCD_DATALINE6 = 1013, - CFG_PIN_LCD_DATALINE7 = 1014, - CFG_NUM_LCD_COLUMNS = 1015, - CFG_NUM_LCD_ROWS = 1016, - // /pxtapp/hf2dbg.h - HF2DBG_H = 1, - // /pxtapp/pins.h - BUTTON_ACTIVE_HIGH_PULL_DOWN = 17, - BUTTON_ACTIVE_HIGH_PULL_UP = 33, - BUTTON_ACTIVE_HIGH_PULL_NONE = 49, - BUTTON_ACTIVE_LOW_PULL_DOWN = 16, - BUTTON_ACTIVE_LOW_PULL_UP = 32, - BUTTON_ACTIVE_LOW_PULL_NONE = 48, - // /pxtapp/platform.h - PAGE_SIZE = 4096, - DEV_NUM_PINS = 32, - IMAGE_BITS = 1, - TEMPERATURE_NOMINAL_VALUE = 25, - TEMPERATURE_NOMINAL_READING = 10000, - TEMPERATURE_BETA = 3380, - TEMPERATURE_SERIES_RESISTOR = 10000, - LIGHTSENSOR_SENSITIVITY = 868, - LIGHTSENSOR_LOW_THRESHOLD = 128, - LIGHTSENSOR_HIGH_THRESHOLD = 896, - P0_0 = 0, - P0_1 = 1, - P0_2 = 2, - P0_3 = 3, - P0_4 = 4, - P0_5 = 5, - P0_6 = 6, - P0_7 = 7, - P0_8 = 8, - P0_9 = 9, - P0_10 = 10, - P0_11 = 11, - P0_12 = 12, - P0_13 = 13, - P0_14 = 14, - P0_15 = 15, - P0_16 = 16, - P0_17 = 17, - P0_18 = 18, - P0_19 = 19, - P0_20 = 20, - P0_21 = 21, - P0_22 = 22, - P0_23 = 23, - P0_24 = 24, - P0_25 = 25, - P0_26 = 26, - P0_27 = 27, - P0_28 = 28, - P0_29 = 29, - P0_30 = 30, - P0_31 = 31, - P1_0 = 32, - P1_1 = 33, - P1_2 = 34, - P1_3 = 35, - P1_4 = 36, - P1_5 = 37, - P1_6 = 38, - P1_7 = 39, - P1_8 = 40, - P1_9 = 41, - P1_10 = 42, - P1_11 = 43, - P1_12 = 44, - P1_13 = 45, - P1_14 = 46, - P1_15 = 47, - P1_16 = 48, - P1_17 = 49, - P1_18 = 50, - P1_19 = 51, - P1_20 = 52, - P1_21 = 53, - P1_22 = 54, - P1_23 = 55, - P1_24 = 56, - P1_25 = 57, - P1_26 = 58, - P1_27 = 59, - P1_28 = 60, - P1_29 = 61, - P1_30 = 62, - P1_31 = 63, - // /pxtapp/pxt.h - DEVICE_ID_BUTTON_SLIDE = 3000, - DEVICE_ID_MICROPHONE = 3001, - DEVICE_ID_FIRST_BUTTON = 4000, - DEVICE_ID_FIRST_TOUCHBUTTON = 4100, - // /pxtapp/pxtbase.h - PXT_REFCNT_FLASH = 65534, - VTABLE_MAGIC = 249, - Undefined = 0, - Boolean = 1, - Number = 2, - String = 3, - Object = 4, - Function = 5, - BoxedString = 1, - BoxedNumber = 2, - BoxedBuffer = 3, - RefAction = 4, - RefImage = 5, - RefCollection = 6, - RefRefLocal = 7, - RefMap = 8, - RefMImage = 9, - User0 = 16, - Int8LE = 1, - UInt8LE = 2, - Int16LE = 3, - UInt16LE = 4, - Int32LE = 5, - Int8BE = 6, - UInt8BE = 7, - Int16BE = 8, - UInt16BE = 9, - Int32BE = 10, - UInt32LE = 11, - UInt32BE = 12, - Float32LE = 13, - Float64LE = 14, - Float32BE = 15, - Float64BE = 16, - GC = 0, - // /pxtapp/pxtconfig.h - PXT_GC = 1, - // /pxtapp/uf2format.h - BOOTLOADER_START = 0, - BOOTLOADER_END = 8192, - // /pxtapp/uf2hid.h - UF2_HID_H = 1, -} diff --git a/libs/core---nrf52832/enums.d.ts b/libs/core---nrf52832/enums.d.ts deleted file mode 100755 index e28759fa..00000000 --- a/libs/core---nrf52832/enums.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Auto-generated. Do not edit. - - - declare const enum PulseValue { - //% block=high - High = 4, // DEVICE_PIN_EVT_PULSE_HI - //% block=low - Low = 5, // DEVICE_PIN_EVT_PULSE_LO - } - - - declare const enum PinEvent { - //% block="pulse high" - PulseHigh = 4, // DEVICE_PIN_EVT_PULSE_HI - //% block="pulse low" - PulseLow = 5, // DEVICE_PIN_EVT_PULSE_LO - //% block="rise" - Rise = 2, // DEVICE_PIN_EVT_RISE - //% block="fall" - Fall = 3, // DEVICE_PIN_EVT_FALL - } - - - declare const enum PinPullMode { - //% block="down" - PullDown = 0, - //% block="up" - PullUp = 1, - //% block="none" - PullNone = 2, - } - -// Auto-generated. Do not edit. Really. diff --git a/libs/core---nrf52832/i2c.cpp b/libs/core---nrf52832/i2c.cpp deleted file mode 100755 index 70b786d1..00000000 --- a/libs/core---nrf52832/i2c.cpp +++ /dev/null @@ -1 +0,0 @@ -// TODO diff --git a/libs/core---nrf52832/i2c.ts b/libs/core---nrf52832/i2c.ts deleted file mode 100755 index 0ffdd02f..00000000 --- a/libs/core---nrf52832/i2c.ts +++ /dev/null @@ -1 +0,0 @@ -// TODO \ No newline at end of file diff --git a/libs/core---nrf52832/platform.cpp b/libs/core---nrf52832/platform.cpp deleted file mode 100755 index b7482a19..00000000 --- a/libs/core---nrf52832/platform.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "pxt.h" - -#include "NRFLowLevelTimer.h" - -namespace pxt { - -NRFLowLevelTimer lowTimer(NRF_TIMER1, TIMER1_IRQn); - -CODAL_TIMER devTimer(lowTimer); - -static void initRandomSeed() { - int seed = 0xC0DA1; - /* - auto pinTemp = LOOKUP_PIN(TEMPERATURE); - if (pinTemp) - seed *= pinTemp->getAnalogValue(); - auto pinLight = LOOKUP_PIN(LIGHT); - if (pinLight) - seed *= pinLight->getAnalogValue(); - */ - seedRandom(seed); -} - -static void disableNFConPins() { - // Ensure NFC pins are configured as GPIO. If not, update the non-volatile UICR. - if (NRF_UICR->NFCPINS) - { - DMESG("RESET UICR\n"); - // Enable Flash Writes - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - // Configure PINS for GPIO use. - NRF_UICR->NFCPINS = 0; - - // Disable Flash Writes - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - // Reset, so the changes can take effect. - NVIC_SystemReset(); - } -} - -void platform_init() { - initRandomSeed(); - - disableNFConPins(); // this is needed when P0_9 and P0_10 are to be used as regular pins - -/* - if (*HF2_DBG_MAGIC_PTR == HF2_DBG_MAGIC_START) { - *HF2_DBG_MAGIC_PTR = 0; - // this will cause alignment fault at the first breakpoint - globals[0] = (TValue)1; - } -*/ - -} - -} - -void cpu_clock_init() { - // missing in Codal -} diff --git a/libs/core---nrf52832/platform.h b/libs/core---nrf52832/platform.h deleted file mode 100755 index 9bab1824..00000000 --- a/libs/core---nrf52832/platform.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __PXT_PLATFORM_H -#define __PXT_PLATFORM_H - -#include "Image.h" -#include "NRF52Microphone.h" -#include "NRF52SPI.h" -#include "NRF52Pin.h" -#include "NRF52PWM.h" -#include "Timer.h" -#include "MultiButton.h" - -#define PAGE_SIZE 4096 - -#define DEV_NUM_PINS 32 - -#define DEV_PWM_PINS 0x0000ffffffffULL // all pins are PWM pins it seems -#define DEV_AIN_PINS 0x0000f000001fULL - -// Codal doesn't yet distinguish between PWM and AIN -#define DEV_ANALOG_PINS (DEV_PWM_PINS | DEV_AIN_PINS) - -#define CODAL_PIN NRF52Pin -#define CODAL_SPI NRF52SPI -#define CODAL_TIMER Timer - -#define IMAGE_BITS 1 - -typedef uint8_t PinName; - -// The parameters below needs tuning! - -/* - * @param nominalValue The value (in SI units) of a nominal position. - * @param nominalReading The raw reading from the sensor at the nominal position. - * @param beta The Steinhart-Hart Beta constant for the device - * @param seriesResistor The value (in ohms) of the resistor in series with the sensor. - * @param zeroOffset Optional zero offset applied to all SI units (e.g. 273.15 for temperature - * sensing in C vs Kelvin). - */ - -#define TEMPERATURE_NOMINAL_VALUE 25 -#define TEMPERATURE_NOMINAL_READING 10000 -#define TEMPERATURE_BETA 3380 -#define TEMPERATURE_SERIES_RESISTOR 10000 -#define TEMPERATURE_ZERO_OFFSET 273.5 - -#define LIGHTSENSOR_SENSITIVITY 868 // codal has 912 now -#define LIGHTSENSOR_LOW_THRESHOLD 128 -#define LIGHTSENSOR_HIGH_THRESHOLD 896 - - -#ifdef JUST_FOR_DAL_D_TS_CPP_WILL_IGNORE -#define P0_0 0 -#define P0_1 1 -#define P0_2 2 -#define P0_3 3 -#define P0_4 4 -#define P0_5 5 -#define P0_6 6 -#define P0_7 7 -#define P0_8 8 -#define P0_9 9 -#define P0_10 10 -#define P0_11 11 -#define P0_12 12 -#define P0_13 13 -#define P0_14 14 -#define P0_15 15 -#define P0_16 16 -#define P0_17 17 -#define P0_18 18 -#define P0_19 19 -#define P0_20 20 -#define P0_21 21 -#define P0_22 22 -#define P0_23 23 -#define P0_24 24 -#define P0_25 25 -#define P0_26 26 -#define P0_27 27 -#define P0_28 28 -#define P0_29 29 -#define P0_30 30 -#define P0_31 31 -#define P1_0 32 -#define P1_1 33 -#define P1_2 34 -#define P1_3 35 -#define P1_4 36 -#define P1_5 37 -#define P1_6 38 -#define P1_7 39 -#define P1_8 40 -#define P1_9 41 -#define P1_10 42 -#define P1_11 43 -#define P1_12 44 -#define P1_13 45 -#define P1_14 46 -#define P1_15 47 -#define P1_16 48 -#define P1_17 49 -#define P1_18 50 -#define P1_19 51 -#define P1_20 52 -#define P1_21 53 -#define P1_22 54 -#define P1_23 55 -#define P1_24 56 -#define P1_25 57 -#define P1_26 58 -#define P1_27 59 -#define P1_28 60 -#define P1_29 61 -#define P1_30 62 -#define P1_31 63 -#endif - -#endif diff --git a/libs/core---nrf52832/pxt.json b/libs/core---nrf52832/pxt.json deleted file mode 100755 index fa8d3774..00000000 --- a/libs/core---nrf52832/pxt.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "core---nrf52832", - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/core", - "cppDependencies": { - "buttons": "file:../buttons", - "light": "file:../light", - "jacdac": "file:../jacdac", - "switch": "file:../switch" - } -} diff --git a/libs/core---nrf52832/shims.d.ts b/libs/core---nrf52832/shims.d.ts deleted file mode 100755 index bd9f63eb..00000000 --- a/libs/core---nrf52832/shims.d.ts +++ /dev/null @@ -1,318 +0,0 @@ -// Auto-generated. Do not edit. -declare namespace light { - - /** - * Send a programmable light buffer to the specified digital pin - * @param data The pin that the light are connected to - * @param clk the clock line if nay - * @param mode the color encoding mode - * @param buf The buffer to send to the pin - */ - //% shim=light::sendBuffer - function sendBuffer(data: DigitalInOutPin, clk: DigitalInOutPin, mode: int32, buf: Buffer): void; -} -declare namespace control { - - /** - * Determines if the USB has been enumerated. - */ - //% shim=control::isUSBInitialized - function isUSBInitialized(): boolean; -} -declare namespace pins { - - /** - * Get a pin by configuration id (DAL.CFG_PIN...) - */ - //% shim=pins::pinByCfg - function pinByCfg(key: int32): DigitalInOutPin; - - /** - * Create a new zero-initialized buffer. - * @param size number of bytes in the buffer - */ - //% shim=pins::createBuffer - function createBuffer(size: int32): Buffer; - - /** - * Get the duration of the last pulse in microseconds. This function should be called from a - * ``onPulsed`` handler. - */ - //% help=pins/pulse-duration blockGap=8 - //% blockId=pins_pulse_duration block="pulse duration (µs)" - //% weight=19 shim=pins::pulseDuration - function pulseDuration(): int32; -} - - -declare interface AnalogInPin { - /** - * Read the connector value as analog, that is, as a value comprised between 0 and 1023. - * @param name pin to write to - */ - //% help=pins/analog-read weight=53 - //% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8" - //% blockNamespace=pins - //% parts="photocell" trackArgs=0 - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=AnalogInPinMethods::analogRead - analogRead(): int32; -} - - -declare interface AnalogOutPin { - /** - * Set the connector value as analog. Value must be comprised between 0 and 1023. - * @param name pin name to write to - * @param value value to write to the pin between ``0`` and ``1023``. eg:1023,0 - */ - //% help=pins/analog-write weight=52 - //% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8 - //% blockNamespace=pins - //% parts="analogled" trackArgs=0 - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% value.min=0 value.max=1023 shim=AnalogOutPinMethods::analogWrite - analogWrite(value: int32): void; -} - - -declare interface DigitalInOutPin { - /** - * Read a pin or connector as either 0 or 1 - * @param name pin to read from - */ - //% help=pins/digital-read weight=61 - //% blockId=device_get_digital_pin block="digital read|pin %name" blockGap=8 - //% parts="slideswitch" trackArgs=0 - //% blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::digitalRead - digitalRead(): boolean; - - /** - * Set a pin or connector value to either 0 or 1. - * @param name pin to write to - * @param value value to set on the pin - */ - //% help=pins/digital-write weight=60 - //% blockId=device_set_digital_pin block="digital write|pin %name|to %value=toggleHighLow" - //% parts="led" trackArgs=0 - //% blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::digitalWrite - digitalWrite(value: boolean): void; - - /** - * Make this pin a digital input, and create events where the timestamp is the duration - * that this pin was either ``high`` or ``low``. - */ - //% help=pins/on-pulsed weight=16 blockGap=8 - //% blockId=pins_on_pulsed block="on|pin %pin|pulsed %pulse" - //% blockNamespace=pins - //% pin.fieldEditor="gridpicker" - //% pin.fieldOptions.width=220 - //% pin.fieldOptions.columns=4 - //% parts="slideswitch" trackArgs=0 - //% deprecated=1 hidden=1 shim=DigitalInOutPinMethods::onPulsed - onPulsed(pulse: PulseValue, body: () => void): void; - - /** - * Register code to run when a pin event occurs. - */ - //% help=pins/on-event weight=20 blockGap=8 - //% blockId=pinsonevent block="on|pin %pin|%event" - //% blockNamespace=pins - //% pin.fieldEditor="gridpicker" - //% pin.fieldOptions.width=220 - //% pin.fieldOptions.columns=4 - //% parts="slideswitch" trackArgs=0 shim=DigitalInOutPinMethods::onEvent - onEvent(event: PinEvent, body: () => void): void; - - /** - * Return the duration of a pulse in microseconds - * @param name the pin which measures the pulse - * @param value the value of the pulse (default high) - * @param maximum duration in micro-seconds - */ - //% blockId="pins_pulse_in" block="pulse in (µs)|pin %name|pulsed %high||timeout %maxDuration (us)" - //% weight=18 blockGap=8 - //% help="pins/pulse-in" - //% blockNamespace=pins - //% pin.fieldEditor="gridpicker" - //% pin.fieldOptions.width=220 - //% pin.fieldOptions.columns=4 maxDuration.defl=2000000 shim=DigitalInOutPinMethods::pulseIn - pulseIn(value: PulseValue, maxDuration?: int32): int32; - - /** - * Set the pull direction of this pin. - * @param name pin to set the pull mode on - * @param pull one of the mbed pull configurations: PullUp, PullDown, PullNone - */ - //% help=pins/set-pull weight=17 blockGap=8 - //% blockId=device_set_pull block="set pull|pin %pin|to %pull" - //% blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=DigitalInOutPinMethods::setPull - setPull(pull: PinPullMode): void; -} - - -declare interface PwmPin {} - - -declare interface PwmOnlyPin { - /** - * Set the Pulse-width modulation (PWM) period of the analog output. The period is in - * **microseconds** or `1/1000` milliseconds. - * If this pin is not configured as an analog output (using `analog write pin`), the operation has - * no effect. - * @param name analog pin to set period to - * @param micros period in micro seconds. eg:20000 - */ - //% help=pins/analog-set-period weight=51 - //% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%period" - //% blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=PwmOnlyPinMethods::analogSetPeriod - analogSetPeriod(period: int32): void; - - /** - * Write a value to the servo to control the rotation of the shaft. On a standard servo, this will - * set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous - * rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one - * direction, ``180`` being full speed in the other, and a value near ``90`` being no movement). - * @param name pin to write to - * @param value angle or rotation speed - */ - //% help=pins/servo-write weight=41 group="Servo" - //% blockId=device_set_servo_pin block="servo write|pin %name|to %value=protractorPicker" blockGap=8 - //% parts=microservo trackArgs=0 - //% blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% value.defl=90 shim=PwmOnlyPinMethods::servoWrite - servoWrite(value?: int32): void; - - /** - * Set the pin for PWM analog output, make the period be 20 ms, and set the pulse width. - * The pulse width is based on the value it is given **microseconds** or `1/1000` milliseconds. - * @param name pin name - * @param duration pulse duration in micro seconds, eg:1500 - */ - //% help=pins/servo-set-pulse weight=40 group="Servo" blockGap=8 - //% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %duration" - //% parts=microservo blockNamespace=pins - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 shim=PwmOnlyPinMethods::servoSetPulse - servoSetPulse(duration: int32): void; -} -declare namespace control { - - /** - * Announce that an event happened to registered handlers. - * @param src ID of the MicroBit Component that generated the event - * @param value Component specific code indicating the cause of the event. - */ - //% weight=21 blockGap=12 blockId="control_raise_event" - //% help=control/raise-event - //% block="raise event|from %src|with value %value" blockExternalInputs=1 shim=control::raiseEvent - function raiseEvent(src: int32, value: int32): void; - - /** - * Determine the version of system software currently running. - */ - //% blockId="control_device_dal_version" block="device dal version" - //% help=control/device-dal-version shim=control::deviceDalVersion - function deviceDalVersion(): string; - - /** - * Allocates the next user notification event - */ - //% help=control/allocate-notify-event shim=control::allocateNotifyEvent - function allocateNotifyEvent(): int32; - - /** Write a message to DMESG debugging buffer. */ - //% shim=control::dmesg - function dmesg(s: string): void; - - /** Write a message and value (pointer) to DMESG debugging buffer. */ - //% shim=control::dmesgPtr - function dmesgPtr(str: string, ptr: Object): void; -} -declare namespace pins { - - /** - * Opens a SPI driver - */ - //% help=pins/create-spi - //% parts=spi shim=pins::createSPI - function createSPI(mosiPin: DigitalInOutPin, misoPin: DigitalInOutPin, sckPin: DigitalInOutPin): SPI; -} - - -declare interface SPI { - /** - * Write to the SPI bus - */ - //% shim=SPIMethods::write - write(value: int32): int32; - - /** - * Transfer buffers over the SPI bus - */ - //% argsNullable shim=SPIMethods::transfer - transfer(command: Buffer, response: Buffer): void; - - /** - * Sets the SPI clock frequency - */ - //% shim=SPIMethods::setFrequency - setFrequency(frequency: int32): void; - - /** - * Sets the SPI bus mode - */ - //% shim=SPIMethods::setMode - setMode(mode: int32): void; -} -declare namespace configStorage { - - /** - * Puts an entry in the device storage. Key may have up to 16 characters (bytes). - * @param key the identifier (max 16 characters) - * @param value the data (max 32 characters) - */ - //% shim=configStorage::setBuffer - function setBuffer(key: string, value: Buffer): void; - - /** - * Gets an entry from the device storage. Key may have up to 16 characters (bytes). - * @param key the identifier (max 16 characters) - */ - //% shim=configStorage::getBuffer - function getBuffer(key: string): Buffer; - - /** - * Removes the key from local storage - * @param key the identifier (max 16 characters) - */ - //% shim=configStorage::removeItem - function removeItem(key: string): void; - - /** - * Clears the local storage - */ - //% shim=configStorage::clear - function clear(): void; -} - -// Auto-generated. Do not edit. Really. diff --git a/libs/core/dal.d.ts b/libs/core/dal.d.ts index 85164554..6e3ac413 100755 --- a/libs/core/dal.d.ts +++ b/libs/core/dal.d.ts @@ -1,121 +1,18 @@ // Auto-generated. Do not edit. declare const enum DAL { - // /libraries/codal-core/inc/JACDAC/JACDAC.h - JD_VERSION = 5, - JD_SERIAL_MAX_BUFFERS = 10, - JD_SERIAL_RECEIVING = 2, - JD_SERIAL_TRANSMITTING = 4, - JD_SERIAL_TX_DRAIN_ENABLE = 8, - JD_SERIAL_BUS_RISE = 16, - JD_SERIAL_EVT_DATA_READY = 1, - JD_SERIAL_EVT_BUS_ERROR = 2, - JD_SERIAL_EVT_DRAIN = 3, - JD_SERIAL_EVT_RX_TIMEOUT = 4, - JD_SERIAL_EVT_BUS_CONNECTED = 5, - JD_SERIAL_EVT_BUS_DISCONNECTED = 6, - JD_SERIAL_HEADER_SIZE = 4, - JD_SERIAL_DATA_SIZE = 32, - JD_SERIAL_PACKET_SIZE = 36, - JD_SERIAL_MAXIMUM_BUFFERS = 10, - JD_SERIAL_DMA_TIMEOUT = 2, - JD_SERIAL_MAX_BAUD = 1000000, - JD_SERIAL_TX_MAX_BACKOFF = 4000, - JD_SERIAL_TX_MIN_BACKOFF = 1000, + // /libraries/codal-core/inc/JACDAC/JDPhysicalLayer.h Receiving = 0, Transmitting = 1, - High = 2, - Low = 3, - Baud1M = 1, - Baud500K = 2, - Baud250K = 4, - Baud125K = 8, - // /libraries/codal-core/inc/JACDAC/JDAccelerometerDriver.h - JD_ACCEL_EVT_SEND_DATA = 1, - // /libraries/codal-core/inc/JACDAC/JDBridgeDriver.h - JD_BRIDGE_HISTORY_SIZE = 8, - // /libraries/codal-core/inc/JACDAC/JDClasses.h + Error = 2, + Unknown = 3, + ListeningForPulse = 0, + ErrorRecovery = 1, + Off = 2, + Continuation = 0, + // /libraries/codal-core/inc/JACDAC/JDServiceClasses.h STATIC_CLASS_START = 0, STATIC_CLASS_END = 16777215, DYNAMIC_CLASS_END = 4294967295, - JD_DRIVER_CLASS_CODAL_START = 0, - JD_DRIVER_CLASS_CODAL_END = 2000, - JD_DRIVER_CLASS_MAKECODE_START = 2000, - JD_DRIVER_CLASS_MAKECODE_END = 4000, - JD_DRIVER_CLASS_CONTROL = 0, - JD_DRIVER_CLASS_JOYSTICK = 1, - JD_DRIVER_CLASS_MESSAGE_BUS = 2, - JD_DRIVER_CLASS_BRIDGE = 3, - JD_DRIVER_CLASS_BUTTON = 4, - JD_DRIVER_CLASS_PIN = 5, - JD_DRIVER_CLASS_RELIABILITY_TESTER = 6, - JD_DRIVER_CLASS_ACCELEROMETER = 7, - JD_DRIVER_CLASS_CAPTOUCH_BUTTON = 8, - // /libraries/codal-core/inc/JACDAC/JDMessageBusDriver.h - JD_MESSAGEBUS_TYPE_EVENT = 1, - JD_MESSAGEBUS_TYPE_LISTEN = 2, - // /libraries/codal-core/inc/JACDAC/JDPinDriver.h - SetDigital = 0, - SetAnalog = 1, - SetServo = 2, - // /libraries/codal-core/inc/JACDAC/JDProtocol.h - JD_DRIVER_EVT_CONNECTED = 65520, - JD_DRIVER_EVT_DISCONNECTED = 65521, - JD_DRIVER_EVT_PAIRED = 65522, - JD_DRIVER_EVT_UNPAIRED = 65523, - JD_DRIVER_EVT_PAIR_REJECTED = 65524, - JD_DRIVER_EVT_PAIRING_RESPONSE = 65525, - JD_DRIVER_EVT_ERROR = 65526, - JD_DEVICE_FLAGS_LOCAL = 32768, - JD_DEVICE_FLAGS_REMOTE = 16384, - JD_DEVICE_FLAGS_BROADCAST = 8192, - JD_DEVICE_FLAGS_PAIR = 4096, - JD_DEVICE_DRIVER_MODE_MSK = 61440, - JD_DEVICE_FLAGS_PAIRABLE = 2048, - JD_DEVICE_FLAGS_PAIRED = 1024, - JD_DEVICE_FLAGS_PAIRING = 512, - JD_DEVICE_FLAGS_INITIALISED = 128, - JD_DEVICE_FLAGS_INITIALISING = 64, - JD_DEVICE_FLAGS_CP_SEEN = 32, - JD_DEVICE_ERROR_MSK = 15, - JD_LOGIC_DRIVER_MAX_FILTERS = 20, - JD_LOGIC_DRIVER_TIMEOUT = 254, - JD_LOGIC_ADDRESS_ALLOC_TIME = 254, - JD_LOGIC_DRIVER_CTRLPACKET_TIME = 112, - JD_LOGIC_DRIVER_EVT_CHANGED = 2, - CONTROL_JD_FLAGS_RESERVED = 32768, - CONTROL_JD_FLAGS_PAIRING_MODE = 16384, - CONTROL_JD_FLAGS_PAIRABLE = 8192, - CONTROL_JD_FLAGS_PAIRED = 4096, - CONTROL_JD_FLAGS_CONFLICT = 2048, - CONTROL_JD_FLAGS_UNCERTAIN = 1024, - CONTROL_JD_FLAGS_NACK = 512, - CONTROL_JD_FLAGS_ACK = 256, - CONTROL_JD_TYPE_HELLO = 1, - CONTROL_JD_TYPE_PAIRING_REQUEST = 2, - CONTROL_JD_TYPE_ERROR = 3, - CONTROL_JD_TYPE_PANIC = 255, - JD_PROTOCOL_EVT_SEND_CONTROL = 1, - JD_PROTOCOL_DRIVER_ARRAY_SIZE = 20, - CONTROL_PACKET_ERROR_NAME_LENGTH = 6, - VirtualDriver = 16384, - PairedDriver = 12288, - HostDriver = 32768, - PairableHostDriver = 34816, - BroadcastDriver = 40960, - SnifferDriver = 24576, - DRIVER_OK = 0, - DRIVER_CALIBRATION_IN_PROGRESS = 1, - DRIVER_CALIBRATION_REQUIRED = 2, - DRIVER_NO_RESOURCES = 3, - DRIVER_BUSY = 4, - DRIVER_COMMS_ERROR = 5, - DRIVER_INVALID_STATE = 6, - DRIVER_PERIPHERAL_MALFUNCTION = 7, - // /libraries/codal-core/inc/JACDAC/JDReliabilityTester.h - RELIABILITY_TEST_FINISHED = 7, - RELIABILITY_STATUS_TEST_IN_PROGRESS = 2, - RELIABILITY_STATUS_TEST_READY = 4, - RELIABILITY_STATUS_TEST_FINISHED = 8, // /libraries/codal-core/inc/core/CodalComponent.h DEVICE_ID_BUTTON_A = 1, DEVICE_ID_BUTTON_B = 2, @@ -145,14 +42,11 @@ declare const enum DAL { DEVICE_ID_GYROSCOPE = 26, DEVICE_ID_HUMIDITY = 27, DEVICE_ID_PRESSURE = 28, - DEVICE_ID_JACDAC0 = 29, - DEVICE_ID_JACDAC1 = 30, - DEVICE_ID_JACDAC_PROTOCOL = 31, - DEVICE_ID_JACKROUTER = 32, - DEVICE_ID_GAME_ENGINE = 33, - DEVICE_ID_GAME_STATE_MANAGER = 34, - DEVICE_ID_SPRITE = 35, - DEVICE_ID_SINGLE_WIRE_SERIAL = 36, + DEVICE_ID_SINGLE_WIRE_SERIAL = 29, + DEVICE_ID_JACDAC = 30, + DEVICE_ID_JACDAC_PHYS = 31, + DEVICE_ID_JACDAC_CONTROL_SERVICE = 32, + DEVICE_ID_JACDAC_CONFIGURATION_SERVICE = 33, DEVICE_ID_IO_P0 = 100, DEVICE_ID_MESSAGE_BUS_LISTENER = 1021, DEVICE_ID_NOTIFY_ONE = 1022, @@ -206,6 +100,7 @@ declare const enum DAL { DEVICE_HEAP_ERROR = 30, DEVICE_NULL_DEREFERENCE = 40, DEVICE_USB_ERROR = 50, + DEVICE_JACDAC_ERROR = 60, DEVICE_HARDWARE_CONFIGURATION_ERROR = 90, // /libraries/codal-core/inc/core/NotifyEvents.h DISPLAY_EVT_FREE = 1, @@ -291,14 +186,16 @@ declare const enum DAL { IO_STATUS_TOUCH_IN = 16, IO_STATUS_EVENT_ON_EDGE = 32, IO_STATUS_EVENT_PULSE_ON_EDGE = 64, + IO_STATUS_INTERRUPT_ON_EDGE = 128, DEVICE_PIN_MAX_OUTPUT = 1023, DEVICE_PIN_MAX_SERVO_RANGE = 180, DEVICE_PIN_DEFAULT_SERVO_RANGE = 2000, DEVICE_PIN_DEFAULT_SERVO_CENTER = 1500, DEVICE_PIN_EVENT_NONE = 0, - DEVICE_PIN_EVENT_ON_EDGE = 1, - DEVICE_PIN_EVENT_ON_PULSE = 2, - DEVICE_PIN_EVENT_ON_TOUCH = 3, + DEVICE_PIN_INTERRUPT_ON_EDGE = 1, + DEVICE_PIN_EVENT_ON_EDGE = 2, + DEVICE_PIN_EVENT_ON_PULSE = 3, + DEVICE_PIN_EVENT_ON_TOUCH = 4, DEVICE_PIN_EVT_RISE = 2, DEVICE_PIN_EVT_FALL = 3, DEVICE_PIN_EVT_PULSE_HI = 4, @@ -399,11 +296,6 @@ declare const enum DAL { HID_KEYBOARD_DELAY_DEFAULT = 10, PressKey = 0, ReleaseKey = 1, - // /libraries/codal-core/inc/drivers/JackRouter.h - AllDown = 1, - HeadPhones = 2, - Buzzer = 3, - BuzzerAndSerial = 4, // /libraries/codal-core/inc/drivers/KeyMap.h KEYMAP_ALL_KEYS_UP_Val = 1, KEYMAP_ALL_KEYS_UP_POS = 28, @@ -415,6 +307,13 @@ declare const enum DAL { KEYMAP_KEY_UP_Val = 0, KEYMAP_KEY_DOWN_Val = 1, KEYMAP_KEY_DOWN_POS = 31, + // /libraries/codal-core/inc/drivers/KeyValueStorage.h + DEVICE_KEY_VALUE_STORE_OFFSET = 4, + KEY_VALUE_STORAGE_MAGIC = 49370, + KEY_VALUE_STORAGE_BLOCK_SIZE = 48, + KEY_VALUE_STORAGE_KEY_SIZE = 16, + KEY_VALUE_STORAGE_SCRATCH_WORD_SIZE = 64, + KEY_VALUE_STORAGE_MAX_PAIRS = 5, // /libraries/codal-core/inc/drivers/LEDMatrix.h LED_MATRIX_GREYSCALE_BIT_DEPTH = 8, LED_MATRIX_EVT_LIGHT_SENSE = 2, @@ -430,51 +329,9 @@ declare const enum DAL { MATRIX_DISPLAY_ROTATION_180 = 2, MATRIX_DISPLAY_ROTATION_270 = 3, NO_CONN = 0, - // /libraries/codal-core/inc/drivers/MAG3110.h - MAG3110_DEFAULT_ADDR = 29, - MAG_DR_STATUS = 0, - MAG_OUT_X_MSB = 1, - MAG_OUT_X_LSB = 2, - MAG_OUT_Y_MSB = 3, - MAG_OUT_Y_LSB = 4, - MAG_OUT_Z_MSB = 5, - MAG_OUT_Z_LSB = 6, - MAG_WHOAMI = 7, - MAG_SYSMOD = 8, - MAG_OFF_X_MSB = 9, - MAG_OFF_X_LSB = 10, - MAG_OFF_Y_MSB = 11, - MAG_OFF_Y_LSB = 12, - MAG_OFF_Z_MSB = 13, - MAG_OFF_Z_LSB = 14, - MAG_DIE_TEMP = 15, - MAG_CTRL_REG1 = 16, - MAG_CTRL_REG2 = 17, - MAG3110_SAMPLE_RATES = 11, - MAG3110_WHOAMI_VAL = 196, - // /libraries/codal-core/inc/drivers/MMA8453.h - MMA8453_DEFAULT_ADDR = 56, - MMA8453_WHOAMI_VAL = 58, // /libraries/codal-core/inc/drivers/MMA8653.h MICROBIT_ACCEL_PITCH_ROLL_VALID = 2, MICROBIT_ACCEL_ADDED_TO_IDLE = 4, - MMA8653_DEFAULT_ADDR = 58, - MMA8653_STATUS = 0, - MMA8653_OUT_X_MSB = 1, - MMA8653_WHOAMI = 13, - MMA8653_XYZ_DATA_CFG = 14, - MMA8653_CTRL_REG1 = 42, - MMA8653_CTRL_REG2 = 43, - MMA8653_CTRL_REG3 = 44, - MMA8653_CTRL_REG4 = 45, - MMA8653_CTRL_REG5 = 46, - MMA8653_WHOAMI_VAL = 90, - MMA8653_SAMPLE_RANGES = 3, - MMA8653_SAMPLE_RATES = 8, - // /libraries/codal-core/inc/drivers/MPU6050.h - MPU6050_DEFAULT_ADDR = 104, - MPU6050_WHOAMI = 117, - MPU6050_WHOAMI_VAL = 52, // /libraries/codal-core/inc/drivers/MultiButton.h MULTI_BUTTON_STATE_1 = 1, MULTI_BUTTON_STATE_2 = 2, @@ -483,14 +340,6 @@ declare const enum DAL { MULTI_BUTTON_SUPRESSED_1 = 16, MULTI_BUTTON_SUPRESSED_2 = 32, MULTI_BUTTON_ATTACHED = 64, - // /libraries/codal-core/inc/drivers/ST7735.h - MADCTL_MY = 128, - MADCTL_MX = 64, - MADCTL_MV = 32, - MADCTL_ML = 16, - MADCTL_RGB = 0, - MADCTL_BGR = 8, - MADCTL_MH = 4, // /libraries/codal-core/inc/drivers/TouchButton.h TOUCH_BUTTON_CALIBRATION_PERIOD = 10, TOUCH_BUTTON_CALIBRATION_LINEAR_OFFSET = 2, @@ -501,6 +350,8 @@ declare const enum DAL { TOUCH_SENSOR_SAMPLE_PERIOD = 50, TOUCH_SENSE_SAMPLE_MAX = 1000, TOUCH_SENSOR_UPDATE_NEEDED = 1, + // /libraries/codal-core/inc/drivers/USBJACDAC.h + JACDAC_USB_STATUS_CLEAR_TO_SEND = 2, // /libraries/codal-core/inc/drivers/USB_HID_Keys.h KEY_MOD_LCTRL = 1, KEY_MOD_LSHIFT = 2, @@ -811,12 +662,32 @@ declare const enum DAL { CFG_PIN_BATTSENSE = 75, CFG_PIN_VIBRATION = 76, CFG_PIN_PWREN = 77, + CFG_DISPLAY_TYPE = 78, + CFG_PIN_ROTARY_ENCODER_A = 79, + CFG_PIN_ROTARY_ENCODER_B = 80, + CFG_ACCELEROMETER_SPACE = 81, + CFG_PIN_WIFI_MOSI = 82, + CFG_PIN_WIFI_MISO = 83, + CFG_PIN_WIFI_SCK = 84, + CFG_PIN_WIFI_TX = 85, + CFG_PIN_WIFI_RX = 86, + CFG_PIN_WIFI_CS = 87, + CFG_PIN_WIFI_BUSY = 88, + CFG_PIN_WIFI_RESET = 89, + CFG_PIN_WIFI_GPIO0 = 90, + CFG_PIN_WIFI_AT_TX = 91, + CFG_PIN_WIFI_AT_RX = 92, + CFG_PIN_USB_POWER = 93, ACCELEROMETER_TYPE_LIS3DH = 50, + ACCELEROMETER_TYPE_LIS3DH_ALT = 48, ACCELEROMETER_TYPE_MMA8453 = 56, ACCELEROMETER_TYPE_FXOS8700 = 60, ACCELEROMETER_TYPE_MMA8653 = 58, ACCELEROMETER_TYPE_MSA300 = 76, ACCELEROMETER_TYPE_MPU6050 = 104, + DISPLAY_TYPE_ST7735 = 7735, + DISPLAY_TYPE_ILI9341 = 9341, + DISPLAY_TYPE_SMART = 4242, CFG_PIN_A0 = 100, CFG_PIN_A1 = 101, CFG_PIN_A2 = 102, @@ -895,6 +766,35 @@ declare const enum DAL { CFG_BOOTLOADER_PROTECTION = 211, CFG_POWER_DEEPSLEEP_TIMEOUT = 212, CFG_ANALOG_BUTTON_THRESHOLD = 213, + CFG_CPU_MHZ = 214, + CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS = 215, + CFG_ANALOG_JOYSTICK_MIN = 216, + CFG_ANALOG_JOYSTICK_MAX = 217, + CFG_TIMERS_TO_USE = 218, + CFG_PIN_ONBOARD_DOTSTAR_CLOCK = 219, + CFG_PIN_ONBOARD_DOTSTAR_DATA = 220, + CFG_NUM_ONBOARD_DOTSTARS = 221, + CFG_PIN_ONBOARD_NEOPIXEL = 222, + CFG_NUM_ONBOARD_NEOPIXELS = 223, + CFG_MATRIX_KEYPAD_MESSAGE_ID = 239, + CFG_NUM_MATRIX_KEYPAD_ROWS = 240, + CFG_PIN_MATRIX_KEYPAD_ROW0 = 241, + CFG_PIN_MATRIX_KEYPAD_ROW1 = 242, + CFG_PIN_MATRIX_KEYPAD_ROW2 = 243, + CFG_PIN_MATRIX_KEYPAD_ROW3 = 244, + CFG_PIN_MATRIX_KEYPAD_ROW4 = 245, + CFG_PIN_MATRIX_KEYPAD_ROW5 = 246, + CFG_PIN_MATRIX_KEYPAD_ROW6 = 247, + CFG_PIN_MATRIX_KEYPAD_ROW7 = 248, + CFG_NUM_MATRIX_KEYPAD_COLS = 250, + CFG_PIN_MATRIX_KEYPAD_COL0 = 251, + CFG_PIN_MATRIX_KEYPAD_COL1 = 252, + CFG_PIN_MATRIX_KEYPAD_COL2 = 253, + CFG_PIN_MATRIX_KEYPAD_COL3 = 254, + CFG_PIN_MATRIX_KEYPAD_COL4 = 255, + CFG_PIN_MATRIX_KEYPAD_COL5 = 256, + CFG_PIN_MATRIX_KEYPAD_COL6 = 257, + CFG_PIN_MATRIX_KEYPAD_COL7 = 258, CFG_PIN_B0 = 300, CFG_PIN_B1 = 301, CFG_PIN_B2 = 302, @@ -980,6 +880,17 @@ declare const enum DAL { CFG_PIN_P18 = 418, CFG_PIN_P19 = 419, CFG_PIN_P20 = 420, + CFG_PIN_P21 = 421, + CFG_PIN_P22 = 422, + CFG_PIN_P23 = 423, + CFG_PIN_P24 = 424, + CFG_PIN_P25 = 425, + CFG_PIN_P26 = 426, + CFG_PIN_P27 = 427, + CFG_PIN_P28 = 428, + CFG_PIN_P29 = 429, + CFG_PIN_P30 = 430, + CFG_PIN_P31 = 431, CFG_PIN_LORA_MISO = 1001, CFG_PIN_LORA_MOSI = 1002, CFG_PIN_LORA_SCK = 1003, @@ -996,14 +907,42 @@ declare const enum DAL { CFG_PIN_LCD_DATALINE7 = 1014, CFG_NUM_LCD_COLUMNS = 1015, CFG_NUM_LCD_ROWS = 1016, + CFG_PIN_RCC0 = 1017, + CFG_PIN_RCC1 = 1018, + CFG_PIN_RCC2 = 1019, + CFG_PIN_RCC3 = 1020, + CFG_PIN_RCC4 = 1021, + CFG_PIN_RCC5 = 1022, + CFG_PIN_RCC6 = 1023, + CFG_PIN_RCC7 = 1024, + CFG_PIN_SERVO0 = 1025, + CFG_PIN_SERVO1 = 1026, + CFG_PIN_SERVO2 = 1027, + CFG_PIN_SERVO3 = 1028, + CFG_PIN_SERVO4 = 1029, + CFG_PIN_SERVO5 = 1030, + CFG_PIN_SERVO6 = 1031, + CFG_PIN_SERVO7 = 1032, + CFG_PIN_SERVO8 = 1033, + CFG_PIN_PI_TX = 1034, + CFG_PIN_PI_RX = 1035, + CFG_PIN_GPS_SDA = 1036, + CFG_PIN_GPS_SCL = 1037, + CFG_PIN_GPS_TX = 1038, + CFG_PIN_GPS_RX = 1039, + CFG_PIN_GROVE0 = 1040, + CFG_PIN_GROVE1 = 1041, + CFG_PIN_SS = 1042, // /pxtapp/hf2dbg.h HF2DBG_H = 1, + // /pxtapp/jacdac/jdprotocol.h + JDSPI_MAGIC = 31437, + JDSPI_MAGIC_NOOP = 46029, // /pxtapp/mixer---samd/melody.h SW_TRIANGLE = 1, SW_SAWTOOTH = 2, SW_SINE = 3, - SW_NOISE = 4, - SW_REAL_NOISE = 5, + SW_NOISE = 5, SW_SQUARE_10 = 11, SW_SQUARE_50 = 15, CODAL = 1, @@ -1020,6 +959,7 @@ declare const enum DAL { BUTTON_ACTIVE_LOW_PULL_NONE = 48, // /pxtapp/platform.h PAGE_SIZE = 512, + BOOTLOADER_START = 0, DEV_NUM_PINS = 64, PXT_74HC165 = 1, IMAGE_BITS = 4, @@ -1092,7 +1032,11 @@ declare const enum DAL { DEVICE_ID_MICROPHONE = 3001, DEVICE_ID_FIRST_BUTTON = 4000, DEVICE_ID_FIRST_TOUCHBUTTON = 4100, + PXT_INTERNAL_KEY_UP = 2050, + PXT_INTERNAL_KEY_DOWN = 2051, // /pxtapp/pxtbase.h + PXT32 = 1, + PXT64 = 1, PXT_REFCNT_FLASH = 65534, VTABLE_MAGIC = 249, Undefined = 0, @@ -1110,7 +1054,10 @@ declare const enum DAL { RefRefLocal = 7, RefMap = 8, RefMImage = 9, + MMap = 10, User0 = 16, + PXT_IOS_HEAP_ALLOC_BITS = 20, + IMAGE_HEADER_MAGIC = 135, Int8LE = 1, UInt8LE = 2, Int16LE = 3, @@ -1127,19 +1074,43 @@ declare const enum DAL { Float64LE = 14, Float32BE = 15, Float64BE = 16, + NUM_TRY_FRAME_REGS = 3, GC = 0, // /pxtapp/pxtconfig.h - PXT_GC = 1, PXT_UF2_FAMILY = 1760373640, - // /pxtapp/storage/SNORFS.h - DEVICE_FLASH_ERROR = 950, + // /pxtapp/serial/serial-common.h + BaudRate115200 = 115200, + BaudRate57600 = 57600, + BaudRate38400 = 38400, + BaudRate31250 = 31250, + BaudRate28800 = 28800, + BaudRate19200 = 19200, + BaudRate14400 = 14400, + BaudRate9600 = 9600, + BaudRate4800 = 4800, + BaudRate2400 = 2400, + BaudRate1200 = 1200, + BaudRate300 = 300, + DataReceived = 4, + RxBufferFull = 3, + NewLine = 10, + Comma = 44, + Dollar = 36, + Colon = 58, + Fullstop = 46, + Hash = 35, + SemiColumn = 59, + Space = 32, + Tab = 9, + Pipe = 124, + // /pxtapp/settings/RAFFS.h + RAFFS_FOLLOWING_MASK = 32768, + RAFFS_FLASH_BUFFER_SIZE = 64, // /pxtapp/thermometer/target_temperature.h TEMPERATURE_NOMINAL_VALUE = 25, TEMPERATURE_NOMINAL_READING = 10000, TEMPERATURE_BETA = 3380, TEMPERATURE_SERIES_RESISTOR = 10000, - // /pxtapp/uf2format.h - BOOTLOADER_START = 0, // /pxtapp/uf2hid.h UF2_HID_H = 1, } diff --git a/libs/keyboard/_locales/keyboard-jsdoc-strings.json b/libs/keyboard/_locales/keyboard-jsdoc-strings.json deleted file mode 100755 index 149f3f77..00000000 --- a/libs/keyboard/_locales/keyboard-jsdoc-strings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "keyboard": "Keyboard emulation", - "keyboard.clearAllKeys": "Send up commands for any remaning down keys", - "keyboard.functionKey": "Send a function key command", - "keyboard.key": "Send a key command", - "keyboard.mediaKey": "Send a media key command", - "keyboard.type": "Send a sequence of keystrokes to the keyboard" -} \ No newline at end of file diff --git a/libs/keyboard/_locales/keyboard-strings.json b/libs/keyboard/_locales/keyboard-strings.json deleted file mode 100755 index 1cad4857..00000000 --- a/libs/keyboard/_locales/keyboard-strings.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "KeyboardFunctionKey.DeleteForward|block": "delete", - "KeyboardFunctionKey.DownArrow|block": "down arrow", - "KeyboardFunctionKey.End|block": "end", - "KeyboardFunctionKey.F10Key|block": "F0", - "KeyboardFunctionKey.F11Key|block": "F11", - "KeyboardFunctionKey.F12Key|block": "F12", - "KeyboardFunctionKey.F1Key|block": "F1", - "KeyboardFunctionKey.F2Key|block": "F2", - "KeyboardFunctionKey.F3Key|block": "F3", - "KeyboardFunctionKey.F4Key|block": "F4", - "KeyboardFunctionKey.F5Key|block": "F5", - "KeyboardFunctionKey.F6Key|block": "F6", - "KeyboardFunctionKey.F7Key|block": "F7", - "KeyboardFunctionKey.F8Key|block": "F8", - "KeyboardFunctionKey.F9Key|block": "F9", - "KeyboardFunctionKey.Home|block": "home", - "KeyboardFunctionKey.Insert|block": "insert", - "KeyboardFunctionKey.LeftArrow|block": "left arrow", - "KeyboardFunctionKey.PageDown|block": "page down", - "KeyboardFunctionKey.PageUp|block": "page up", - "KeyboardFunctionKey.Pause|block": "pause", - "KeyboardFunctionKey.PrintScreen|block": "print screen", - "KeyboardFunctionKey.RightArrow|block": "right arrow", - "KeyboardFunctionKey.ScrollLock|block": "scroll lock", - "KeyboardFunctionKey.UpArrow|block": "up arrow", - "KeyboardKeyEvent.Down|block": "down", - "KeyboardKeyEvent.Press|block": "press", - "KeyboardKeyEvent.Up|block": "up", - "KeyboardMediaKey.Calculator|block": "calculator", - "KeyboardMediaKey.Mail|block": "mail", - "KeyboardMediaKey.Mute|block": "mute", - "KeyboardMediaKey.NextTrack|block": "next track", - "KeyboardMediaKey.PlayPause|block": "play pause", - "KeyboardMediaKey.PreviousTrack|block": "previous track", - "KeyboardMediaKey.Stop|block": "stop", - "KeyboardMediaKey.VolumeDown|block": "volume down", - "KeyboardMediaKey.VolumeUp|block": "volume up", - "KeyboardMediaKey.WebBack|block": "web back", - "KeyboardMediaKey.WebFavourites|block": "web favourites", - "KeyboardMediaKey.WebForward|block": "web forward", - "KeyboardMediaKey.WebHome|block": "web home", - "KeyboardMediaKey.WebRefresh|block": "web refresh", - "KeyboardMediaKey.WebSearch|block": "web search", - "KeyboardMediaKey.WebStop|block": "web stop", - "jacdac.keyboardService|block": "keyboard service", - "keyboard.clearAllKeys|block": "keyboard clear all", - "keyboard.functionKey|block": "keyboard function key %key|%event", - "keyboard.key|block": "keyboard key %key|%event", - "keyboard.mediaKey|block": "keyboard media key %key|%event", - "keyboard.type|block": "keyboard type %text", - "keyboard|block": "keyboard", - "{id:category}Jacdac": "Jacdac", - "{id:category}Keyboard": "Keyboard" -} \ No newline at end of file diff --git a/libs/keyboard/enums.d.ts b/libs/keyboard/enums.d.ts deleted file mode 100755 index a97729b2..00000000 --- a/libs/keyboard/enums.d.ts +++ /dev/null @@ -1,107 +0,0 @@ -// Auto-generated. Do not edit. - - - declare const enum KeyboardMediaKey - { - //% block="mute" - Mute = 0, - //% block="volume up" - VolumeUp = 1, - //% block="volume down" - VolumeDown = 2, - //% block="play pause" - PlayPause = 3, - //% block="stop" - Stop = 4, - //% block="previous track" - PreviousTrack = 5, - //% block="next track" - NextTrack = 6, - //% block="mail" - Mail = 7, - //% block="calculator" - Calculator = 8, - //% block="web search" - WebSearch = 9, - //% block="web home" - WebHome = 10, - //% block="web favourites" - WebFavourites = 11, - //% block="web refresh" - WebRefresh = 12, - //% block="web stop" - WebStop = 13, - //% block="web forward" - WebForward = 14, - //% block="web back" - WebBack = 15, - } - - - declare const enum KeyboardFunctionKey - { - //% block="F1" - F1Key = 0, - //% block="F2" - F2Key = 1, - //% block="F3" - F3Key = 2, - //% block="F4" - F4Key = 3, - //% block="F5" - F5Key = 4, - //% block="F6" - F6Key = 5, - //% block="F7" - F7Key = 6, - //% block="F8" - F8Key = 7, - //% block="F9" - F9Key = 8, - //% block="F0" - F10Key = 9, - //% block="F11" - F11Key = 10, - //% block="F12" - F12Key = 11, - - //% block="print screen" - PrintScreen = 12, - //% block="scroll lock" - ScrollLock = 13, - //% block="pause" - Pause = 14, - //% block="insert" - Insert = 15, - //% block="home" - Home = 16, - //% block="page up" - PageUp = 17, - //% block="delete" - DeleteForward = 18, - //% block="end" - End = 19, - //% block="page down" - PageDown = 20, - - //% block="right arrow" - RightArrow = 21, - //% block="left arrow" - LeftArrow = 22, - //% block="down arrow" - DownArrow = 23, - //% block="up arrow" - UpArrow = 24, - } - - - declare const enum KeyboardKeyEvent { - //% block="press" - Press = 0, - //% block="up" - Up = 1, - //% block="down" - Down = 2, - } - -// Auto-generated. Do not edit. Really. diff --git a/libs/keyboard/pxt.json b/libs/keyboard/pxt.json deleted file mode 100755 index 46ad4a4d..00000000 --- a/libs/keyboard/pxt.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/keyboard" -} diff --git a/libs/keyboard/shims.d.ts b/libs/keyboard/shims.d.ts deleted file mode 100755 index 479f02b3..00000000 --- a/libs/keyboard/shims.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Auto-generated. Do not edit. -declare namespace keyboard { - - //% shim=keyboard::__type hidden=1 - function __type(text: string): void; - - //% shim=keyboard::__key hidden=1 - function __key(ckey: number, event: KeyboardKeyEvent): void; - - //% shim=keyboard::__mediaKey hidden=1 - function __mediaKey(key: KeyboardMediaKey, event: KeyboardKeyEvent): void; - - //% shim=keyboard::__functionKey hidden=1 - function __functionKey(key: KeyboardFunctionKey, event: KeyboardKeyEvent): void; -} - -// Auto-generated. Do not edit. Really. diff --git a/libs/lightsensor/pxt.json b/libs/lightsensor/pxt.json index f41474c6..d6be2377 100755 --- a/libs/lightsensor/pxt.json +++ b/libs/lightsensor/pxt.json @@ -2,13 +2,11 @@ "name": "lightsensor", "description": "Onboard light level sensor", "dependencies": { - "core": "file:../core", - "jacdac": "file:../jacdac" + "core": "file:../core" }, "files": [ "README.md", "lightsensor.cpp", - "jacdac.ts", "ns.ts", "shims.d.ts", "enums.d.ts" diff --git a/libs/servo/targetoverrides.ts b/libs/servo/targetoverrides.ts deleted file mode 100755 index cb457d11..00000000 --- a/libs/servo/targetoverrides.ts +++ /dev/null @@ -1,6 +0,0 @@ -namespace servos { - //% block="servo A1" fixedInstance - export const A1 = new servos.PinServo(pins.SERVO_LEFT); - //% block="servo A2" fixedInstance - export const A2 = new servos.PinServo(pins.SERVO_RIGHT); -} \ No newline at end of file diff --git a/libs/switch/pxt.json b/libs/switch/pxt.json index 74f7361f..3d051e20 100755 --- a/libs/switch/pxt.json +++ b/libs/switch/pxt.json @@ -2,16 +2,14 @@ "name": "switch", "description": "A slide switch", "dependencies": { - "core": "file:../core", - "jacdac": "file:../jacdac" + "core": "file:../core" }, "files": [ "README.md", "switch.cpp", "ns.ts", "shims.d.ts", - "enums.d.ts", - "jacdac.ts" + "enums.d.ts" ], "public": true, "additionalFilePath": "../../node_modules/pxt-common-packages/libs/switch" diff --git a/libs/teknikio-bluebird/pxt.json b/libs/teknikio-bluebird/pxt.json index 54185cec..d1c0ddff 100755 --- a/libs/teknikio-bluebird/pxt.json +++ b/libs/teknikio-bluebird/pxt.json @@ -5,7 +5,6 @@ "core---nrf52": "file:../core---nrf52", "mixer---nrf52": "file:../mixer---nrf52", "pulse": "file:../pulse", - "jacdac": "file:../jacdac", "servo": "file:../servo", "accelerometer": "file:../accelerometer", "lightsensor": "file:../lightsensor", diff --git a/libs/touch/_locales/touch-jsdoc-strings.json b/libs/touch/_locales/touch-jsdoc-strings.json deleted file mode 100755 index 45b88a4d..00000000 --- a/libs/touch/_locales/touch-jsdoc-strings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "AnalogInOutPin.touchButton": "Get the cap-touch sensor for given pin (if available)", - "TouchButton.calibrate": "Calibrate the touch sensivity", - "TouchButton.setThreshold": "Manually define the threshold use to detect a touch event. Any sensed value equal to or greater than this value will be interpreted as a touch.", - "TouchButton.setThreshold|param|threshold": "minimum value to consider a touch eg:200", - "TouchButton.threshold": "Gets the current threshold", - "TouchButton.value": "Reads the current value registered with the button." -} \ No newline at end of file diff --git a/libs/touch/_locales/touch-strings.json b/libs/touch/_locales/touch-strings.json deleted file mode 100755 index bbc06815..00000000 --- a/libs/touch/_locales/touch-strings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "TouchButton.calibrate|block": "button %button calibrate", - "TouchButton.setThreshold|block": "button %button|set threshold %threshold", - "TouchButton.threshold|block": "button %button|threshold", - "TouchButton.value|block": "button %button|value", - "{id:category}AnalogInOutPin": "AnalogInOutPin", - "{id:category}Input": "Input", - "{id:group}More": "More" -} \ No newline at end of file diff --git a/libs/touch/pxt.json b/libs/touch/pxt.json deleted file mode 100755 index e021b78b..00000000 --- a/libs/touch/pxt.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "touch", - "description": "The capacitive touch library", - "files": [ - "README.md", - "touch.h", - "touch.cpp", - "touch.ts", - "shims.d.ts", - "enums.d.ts" - ], - "testFiles": [ - "test.ts" - ], - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/touch", - "public": true, - "dependencies": { - "core": "file:../core", - "buttons": "file:../buttons" - } -} diff --git a/libs/touch/shims.d.ts b/libs/touch/shims.d.ts deleted file mode 100755 index 6ac14f2f..00000000 --- a/libs/touch/shims.d.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Auto-generated. Do not edit. - - -declare interface TouchButton { - /** - * Manually define the threshold use to detect a touch event. Any sensed value equal to or greater than this value will be interpreted as a touch. - * @param name button name - * @param threshold minimum value to consider a touch eg:200 - */ - //% blockId=touch_set_threshold block="button %button|set threshold %threshold" - //% blockNamespace=input - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% threshold.min=0 - //% threshold.max=1023 - //% group="More" weight=16 blockGap=8 - //% help=input/touch/set-threshold shim=TouchButtonMethods::setThreshold - setThreshold(threshold: int32): void; - - /** - * Gets the current threshold - * @param name button name - */ - //% blockId=touch_threshold block="button %button|threshold" - //% blockNamespace=input - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% group="More" weight=16 blockGap=8 - //% help=input/touch/threshold shim=TouchButtonMethods::threshold - threshold(): int32; - - /** - * Reads the current value registered with the button. - * @param name button name - */ - //% blockId=touch_value block="button %button|value" - //% blockNamespace=input - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% group="More" weight=49 blockGap=8 - //% help=input/touch/value shim=TouchButtonMethods::value - value(): int32; - - /** - * Calibrate the touch sensivity - */ - //% blockId=touch_calibrate block="button %button calibrate" - //% blockNamespace=input - //% name.fieldEditor="gridpicker" - //% name.fieldOptions.width=220 - //% name.fieldOptions.columns=4 - //% group="More" weight=49 blockGap=8 - //% help=input/touch/calibrate shim=TouchButtonMethods::calibrate - calibrate(): void; -} - - -declare interface AnalogInOutPin { - /** - * Get the cap-touch sensor for given pin (if available) - */ - //% shim=AnalogInOutPinMethods::touchButton - touchButton(): TouchButton; -} - -// Auto-generated. Do not edit. Really. diff --git a/package-lock.json b/package-lock.json index 7a41a11a..54ff62b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3198,26 +3198,6 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, "lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", @@ -4533,369 +4513,6 @@ } } }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "requires": { - "postcss": "^5.0.5" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - } - } - }, - "postcss-normalize-display-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", - "requires": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "postcss-normalize-unicode": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", diff --git a/package.json b/package.json index 852bdaa3..9c964021 100755 --- a/package.json +++ b/package.json @@ -35,13 +35,13 @@ "dependencies": { "@types/bluebird": "2.0.33", "@types/marked": "0.3.0", - "@types/node": "8.0.53", + "@types/node": "8.10.66", "@types/react": "16.0.25", "@types/react-dom": "16.0.3", "@types/web-bluetooth": "0.0.4", "jquery": "^3.5.1", - "pxt-common-packages": "6.21.5", - "pxt-core": "^6.1.18", + "pxt-common-packages": "8.9.14", + "pxt-core": "6.13.55", "react": "16.8.3", "semantic-ui-less": "2.2.14", "svgo": "^1.3.2", diff --git a/pxtarget.json b/pxtarget.json index bba27d60..8da84377 100755 --- a/pxtarget.json +++ b/pxtarget.json @@ -7,21 +7,17 @@ "bundleddirs": [ "libs/base", "libs/core", - "libs/buttons", "libs/accelerometer", "libs/music", "libs/lightsensor", "libs/color", "libs/light", - "libs/touch", "libs/switch", "libs/pulse", "libs/mouse", - "libs/keyboard", "libs/gamepad", "libs/storage", "libs/serial", - "libs/jacdac", "libs/servo", "libs/core---nrf52", "libs/teknikio-bluebird", diff --git a/sim/simulator.ts b/sim/simulator.ts index 5e99212a..7ce1eb9d 100755 --- a/sim/simulator.ts +++ b/sim/simulator.ts @@ -1,4 +1,5 @@ /// +/// namespace pxsim { @@ -24,11 +25,9 @@ namespace pxsim { CapTouchBoard, AccelerometerBoard, StorageBoard, - JacDacBoard, LightSensorBoard, MicrophoneBoard, ScreenBoard, - InfraredBoard, LCDBoard { // state & update logic for component services radioState: RadioState; @@ -43,16 +42,14 @@ namespace pxsim { touchButtonState: TouchButtonState; accelerometerState: AccelerometerState; storageState: StorageState; - jacdacState: JacDacState; microphoneState: AnalogSensorState; screenState: ScreenState; - irState: InfraredState; lcdState: LCDState; constructor(public boardDefinition: BoardDefinition) { super(); - this.bus = new EventBus(runtime); + //this.bus = new EventBus(runtime); const pinList: number[] = [] const servos: Map = {} @@ -106,15 +103,13 @@ namespace pxsim { //this.lightState = {}; this.microphoneState = new AnalogSensorState(DAL.DEVICE_ID_MICROPHONE, 52, 120, 75, 96); this.storageState = new StorageState(); - this.jacdacState = new JacDacState(this); this.lightSensorState = new AnalogSensorState(DAL.DEVICE_ID_LIGHT_SENSOR, 0, 255, 128 / 4, 896 / 4); - this.irState = new InfraredState(); this.lcdState = new LCDState(); this.bus.setNotify(DAL.DEVICE_ID_NOTIFY, DAL.DEVICE_ID_NOTIFY_ONE); // TODO we need this.buttonState set for pxtcore.getButtonByPin(), but // this should be probably merged with buttonpair somehow - this.builtinParts["radio"] = this.radioState = new RadioState(runtime, { + this.builtinParts["radio"] = this.radioState = new RadioState(runtime, this, { ID_RADIO: DAL.DEVICE_ID_RADIO, RADIO_EVT_DATAGRAM: 1 /*DAL.DEVICE_RADIO_EVT_DATAGRAM*/ }); @@ -137,11 +132,11 @@ namespace pxsim { this.builtinVisuals["microservo"] = () => new visuals.MicroServoView(); this.builtinParts["neopixel"] = (pin: Pin) => { return this.neopixelState(pin.id); }; - this.builtinVisuals["neopixel"] = () => new visuals.NeoPixelView(); + this.builtinVisuals["neopixel"] = () => new visuals.NeoPixelView(parsePinString); this.builtinPartVisuals["neopixel"] = (xy: visuals.Coord) => visuals.mkNeoPixelPart(xy); this.builtinParts["dotstar"] = (pin: Pin) => { return this.neopixelState(pin.id); }; - this.builtinVisuals["dotstar"] = () => new visuals.NeoPixelView(); + this.builtinVisuals["dotstar"] = () => new visuals.NeoPixelView(parsePinString); this.builtinPartVisuals["dotstar"] = (xy: visuals.Coord) => visuals.mkNeoPixelPart(xy); this.builtinParts["lcd"] = this.lcdState; @@ -149,7 +144,7 @@ namespace pxsim { this.builtinPartVisuals["lcd"] = (xy: visuals.Coord) => visuals.mkLCDPart(xy); this.builtinParts["pixels"] = (pin: Pin) => { return this.neopixelState(undefined); }; - this.builtinVisuals["pixels"] = () => new visuals.NeoPixelView(); + this.builtinVisuals["pixels"] = () => new visuals.NeoPixelView(parsePinString); this.builtinPartVisuals["pixels"] = (xy: visuals.Coord) => visuals.mkNeoPixelPart(xy); this.builtinPartVisuals["buttons"] = (xy: visuals.Coord) => visuals.mkBtnSvg(xy); @@ -196,10 +191,6 @@ namespace pxsim { let packet = msg; //this.radioState.recievePacket(packet); break; - case "irpacket": - let irpacket = msg; - this.irState.receive(irpacket.packet); - break; } } diff --git a/sim/tsconfig.json b/sim/tsconfig.json index 007366f2..aaf9c239 100755 --- a/sim/tsconfig.json +++ b/sim/tsconfig.json @@ -1,12 +1,13 @@ { "compilerOptions": { - "target": "es5", + "target": "es2017", "noImplicitAny": true, "noImplicitReturns": true, "declaration": true, "out": "../built/sim.js", "rootDir": ".", "newLine": "LF", - "sourceMap": false + "sourceMap": false, + "typeRoots": ["../node_modules/@types"] } } diff --git a/sim/visuals/neopixel.ts b/sim/visuals/neopixel.ts deleted file mode 100755 index a51d9ffb..00000000 --- a/sim/visuals/neopixel.ts +++ /dev/null @@ -1,238 +0,0 @@ -/// -/// -/// - -namespace pxsim.visuals { - const PIXEL_SPACING = PIN_DIST * 3; - const PIXEL_RADIUS = PIN_DIST; - const CANVAS_WIDTH = 1.2 * PIN_DIST; - const CANVAS_HEIGHT = 12 * PIN_DIST; - const CANVAS_VIEW_WIDTH = CANVAS_WIDTH; - const CANVAS_VIEW_HEIGHT = CANVAS_HEIGHT; - const CANVAS_VIEW_PADDING = PIN_DIST * 4; - const CANVAS_LEFT = 1.4 * PIN_DIST; - const CANVAS_TOP = PIN_DIST; - - // For the instructions parts list - export function mkNeoPixelPart(xy: Coord = [0, 0]): SVGElAndSize { - const NP_PART_XOFF = -13.5; - const NP_PART_YOFF = -11; - const NP_PART_WIDTH = 87.5; - const NP_PART_HEIGHT = 190; - const NEOPIXEL_PART_IMG = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -`; - let [x, y] = xy; - let l = x + NP_PART_XOFF; - let t = y + NP_PART_YOFF; - let w = NP_PART_WIDTH; - let h = NP_PART_HEIGHT; - let img = svg.elt("image"); - svg.hydrate(img, { - class: "sim-neopixel-strip", x: l, y: t, width: w, height: h, - href: svg.toDataUri(NEOPIXEL_PART_IMG) - }); - return { el: img, x: l, y: t, w: w, h: h }; - } - export class NeoPixel { - public el: SVGElement; - public cy: number; - - constructor(xy: Coord = [0, 0]) { - let el = svg.elt("rect"); - let r = PIXEL_RADIUS; - let [cx, cy] = xy; - let y = cy - r; - svg.hydrate(el, { x: "-50%", y: y, width: "100%", height: r * 2, class: "sim-neopixel" }); - this.el = el; - this.cy = cy; - } - - public setRgb(rgb: [number, number, number]) { - let hsl = visuals.rgbToHsl(rgb); - let [h, s, l] = hsl; - // at least 70% luminosity - l = Math.max(l, 60); - let fill = `hsl(${h}, ${s}%, ${l}%)`; - this.el.setAttribute("fill", fill); - } - } - - export class NeoPixelCanvas { - public canvas: SVGSVGElement; - public pin: number; - public pixels: NeoPixel[]; - private viewBox: [number, number, number, number]; - private background: SVGRectElement; - - constructor(pin: number) { - this.pixels = []; - this.pin = pin; - let el = svg.elt("svg"); - svg.hydrate(el, { - "class": `sim-neopixel-canvas`, - "x": "0px", - "y": "0px", - "width": `${CANVAS_WIDTH}px`, - "height": `${CANVAS_HEIGHT}px`, - }); - this.canvas = el; - this.background = svg.child(el, "rect", { class: "sim-neopixel-background hidden" }); - this.updateViewBox(-CANVAS_VIEW_WIDTH / 2, 0, CANVAS_VIEW_WIDTH, CANVAS_VIEW_HEIGHT); - } - - private updateViewBox(x: number, y: number, w: number, h: number) { - this.viewBox = [x, y, w, h]; - svg.hydrate(this.canvas, { "viewBox": `${x} ${y} ${w} ${h}` }); - svg.hydrate(this.background, { "x": x, "y": y, "width": w, "height": h }); - } - - public update(colors: number[][]) { - if (!colors || colors.length <= 0) - return; - - for (let i = 0; i < colors.length; i++) { - let pixel = this.pixels[i]; - if (!pixel) { - let cxy: Coord = [0, CANVAS_VIEW_PADDING + i * PIXEL_SPACING]; - pixel = this.pixels[i] = new NeoPixel(cxy); - svg.hydrate(pixel.el, { title: `offset: ${i}` }); - this.canvas.appendChild(pixel.el); - } - let color = colors[i]; - pixel.setRgb(color as [number, number, number]); - } - - //show the canvas if it's hidden - pxsim.U.removeClass(this.background, "hidden"); - - //resize if necessary - let [first, last] = [this.pixels[0], this.pixels[this.pixels.length - 1]] - let yDiff = last.cy - first.cy; - let newH = yDiff + CANVAS_VIEW_PADDING * 2; - let [oldX, oldY, oldW, oldH] = this.viewBox; - if (oldH < newH) { - let scalar = newH / oldH; - let newW = oldW * scalar; - this.updateViewBox(-newW / 2, oldY, newW, newH); - } - } - - public setLoc(xy: Coord) { - let [x, y] = xy; - svg.hydrate(this.canvas, { x: x, y: y }); - } - }; - - function digitalPinToPinNumber(gpioPin: string): number { - const MICROBIT_ID_IO_P0 = 7; //TODO: don't hardcode this, import enums.d.ts - if (gpioPin == "*") { - return MICROBIT_ID_IO_P0; - } - const pin = /^(\w+)\.((P|A|D)(\d+))$/.exec(gpioPin); - //TODO: fix assert - //let pinSplit = gpioPin.split("DigitalPin.P"); - //U.assert(pinSplit.length === 2, "Unknown format for pin (for NeoPixel): " + gpioPin); - //let pinNumStr = pinSplit[1]; - let pinNum = Number(pin[4]) + MICROBIT_ID_IO_P0; - return pinNum - } - - export class NeoPixelView implements IBoardPart { - public style: string = ` - .sim-neopixel-canvas { - } - .sim-neopixel-canvas-parent:hover { - transform-origin: center; - transform: scale(4) translateY(-60px); - -moz-transform: scale(4) translateY(-220px); - } - .sim-neopixel-canvas .hidden { - visibility:hidden; - } - .sim-neopixel-background { - fill: rgba(255,255,255,0.9); - } - .sim-neopixel-strip { - } - `; - public element: SVGElement; - public overElement: SVGElement; - public defs: SVGElement[]; - private state: CommonNeoPixelState; - private canvas: NeoPixelCanvas; - private part: SVGElAndSize; - private stripGroup: SVGGElement; - private lastLocation: Coord; - private pin: Pin; - - public init(bus: EventBus, state: CommonNeoPixelStateConstructor, svgEl: SVGSVGElement, otherParams: Map): void { - this.stripGroup = svg.elt("g"); - this.element = this.stripGroup; - this.pin = parsePinString(otherParams["dataPin"] || otherParams["pin"]) - || parsePinString("pins.NEOPIXEL") - || parsePinString("pins.MOSI"); - this.lastLocation = [0, 0]; - this.state = state(this.pin); - - let part = mkNeoPixelPart(); - this.part = part; - this.stripGroup.appendChild(part.el); - let canvas = new NeoPixelCanvas(this.pin.id); - this.canvas = canvas; - let canvasG = svg.elt("g", { class: "sim-neopixel-canvas-parent" }); - this.overElement = canvasG; - canvasG.appendChild(canvas.canvas); - this.updateStripLoc(); - } - public moveToCoord(xy: Coord): void { - let [x, y] = xy; - let loc: Coord = [x, y]; - this.lastLocation = loc; - this.updateStripLoc(); - } - private updateStripLoc() { - let [x, y] = this.lastLocation; - U.assert(typeof x === "number" && typeof y === "number", "invalid x,y for NeoPixel strip"); - this.canvas.setLoc([x + CANVAS_LEFT, y + CANVAS_TOP]); - svg.hydrate(this.part.el, { transform: `translate(${x} ${y})` }); //TODO: update part's l,h, etc. - } - public updateState(): void { - console.log("====> Update NeoPixel state"); - let colors: number[][] = []; - for (let i = 0; i < this.state.length; i++) { - colors.push(this.state.pixelColor(i)); - } - this.canvas.update(colors); - } - public updateTheme(): void { } - } -} diff --git a/yarn.lock b/yarn.lock index 32cb6c89..d238b1ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,6 @@ # yarn lockfile v1 -"@jacdac/jacdac-ts@^0.0.9": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@jacdac/jacdac-ts/-/jacdac-ts-0.0.9.tgz#477af57ef268d79f79e1d5b13e3e79da840dadef" - integrity sha512-eMps8XvVwHXTQFkQu8SZAKaBczufk4ubp3uoU4+q5fipDgPXRfO3ykHxTgj5gtk5ZjVq/zNMfSlB3is7ohQtIw== - dependencies: - "@types/w3c-web-usb" "^1.0.3" - webusb "^1.1.1" - "@microsoft/immersive-reader-sdk@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@microsoft/immersive-reader-sdk/-/immersive-reader-sdk-1.1.0.tgz#8e8dc0789f552d3fedea22716c5b4843bf95a708" @@ -35,12 +27,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26" integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA== -"@types/node@8.0.53": - version "8.0.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.53.tgz#396b35af826fa66aad472c8cb7b8d5e277f4e6d8" - integrity sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ== - -"@types/node@^8.0.54": +"@types/node@8.10.66": version "8.10.66" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== @@ -82,18 +69,6 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== -"@types/usb@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/usb/-/usb-1.5.2.tgz#bb7d325908af547b69dc0f0b70030cc23b9839fd" - integrity sha512-mYGrpSQ+qYApVDQRXdjnbMpFxuO9o85YO6EfTAZwEWNZf4ptbWTT59g3WmyA/QmpecAD3ZRjdN0UkpZGcu/TVg== - dependencies: - "@types/node" "*" - -"@types/w3c-web-usb@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@types/w3c-web-usb/-/w3c-web-usb-1.0.4.tgz#57e4181041dc1ad2bfad59b737caa7bddc7e1a27" - integrity sha512-aaOB3EL5WCWBBOYX7W1MKuzspOM9ZJI9s3iziRVypr1N+QyvIgXzCM4lm1iiOQ1VFzZioUPX9bsa23myCbKK4A== - "@types/web-bluetooth@0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.4.tgz#107b7fc8666470035b541b194c933d320cd8fb47" @@ -167,16 +142,6 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -197,19 +162,6 @@ applicationinsights-js@^1.0.20: resolved "https://registry.yarnpkg.com/applicationinsights-js/-/applicationinsights-js-1.0.21.tgz#30461c672644c3d34615a0417dd45d97c48eed9f" integrity sha512-AUkkm8OWfCgbBuMe7kSAwUFpc1e2y+WisieQx/VgCS+BT/0AubmnGZ1yQ+zkENVriM9qArKNjLqTQp38x995wg== -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -343,32 +295,11 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bindings@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - blob@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== -bluebird@3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA== - bluebird@^3.3.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -622,7 +553,7 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= -buffer@^5.0.2, buffer@^5.5.0: +buffer@^5.0.2: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -730,11 +661,6 @@ chokidar@^3.0.0: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -757,11 +683,6 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -842,11 +763,6 @@ commander@~2.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" integrity sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E= -commander@~2.15.0: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" @@ -892,11 +808,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -1171,13 +1082,6 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - deep-eql@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" @@ -1185,11 +1089,6 @@ deep-eql@^0.1.3: dependencies: type-detect "0.1.1" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1207,11 +1106,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1235,11 +1129,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -1396,13 +1285,6 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - engine.io-client@~3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" @@ -1536,11 +1418,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - extend@^3.0.0, extend@~3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -1595,11 +1472,6 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1661,11 +1533,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -1690,20 +1557,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-assigned-identifiers@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" @@ -1725,11 +1578,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1829,11 +1677,6 @@ has-symbols@^1.0.1, has-symbols@^1.0.2: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2031,11 +1874,6 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - inline-source-map@~0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" @@ -2137,18 +1975,6 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -2525,11 +2351,6 @@ mime@^2.0.3, mime@^2.3.1: resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2557,7 +2378,7 @@ minimist@1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -2567,11 +2388,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -2639,38 +2455,16 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -napi-build-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" - integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -node-abi@^2.7.0: - version "2.30.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.30.0.tgz#8be53bf3e7945a34eea10e0fc9a5982776cf550b" - integrity sha512-g6bZh3YCKQRdwuO/tSZZYJAw622SjsRfJ2X0Iy4sSOHZ34/sPPdVBn8fev2tj7njzLwuqPw9uMtGsGkO5kIQvg== - dependencies: - semver "^5.4.1" - -node-addon-api@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.2.tgz#04bc7b83fd845ba785bb6eae25bc857e1ef75681" - integrity sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg== - node-releases@^1.1.71: version "1.1.73" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -2681,16 +2475,6 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -2698,11 +2482,6 @@ nth-check@^1.0.2: dependencies: boolbase "~1.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -2713,7 +2492,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -2768,7 +2547,7 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -3199,27 +2978,6 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27: source-map "^0.6.1" supports-color "^6.1.0" -prebuild-install@^5.3.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291" - integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -3292,14 +3050,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -3331,21 +3081,20 @@ puppeteer@^2.0.0: rimraf "^2.6.1" ws "^6.1.0" -pxt-common-packages@6.21.5: - version "6.21.5" - resolved "https://registry.yarnpkg.com/pxt-common-packages/-/pxt-common-packages-6.21.5.tgz#fe5d9ea37de2b1dd3d19d653c743817797481b0a" - integrity sha512-W0OjMGiyAVwyesh0BpZaDZvNOW5V8p8KOak2u8yI2mXS+F05mVzbmfS0wvCTnlDAM5jdTTKBlWTTqg+US7UV5w== +pxt-common-packages@8.9.14: + version "8.9.14" + resolved "https://registry.yarnpkg.com/pxt-common-packages/-/pxt-common-packages-8.9.14.tgz#71dfebd84b80d6cf566c23697ac19ba613ae7157" + integrity sha512-EQOAnInqFtZtaSEkR0SXAmeKvdYYVvKr1pad3kQqL9Jt2xAr0WkJ2jB7lf4sUY280r7/n9YSy6F0IoPPDI5Rxw== dependencies: - "@jacdac/jacdac-ts" "^0.0.9" - pxt-core "^5.34.1" + pxt-core "^6.13.9" -pxt-core@^5.34.1: - version "5.37.83" - resolved "https://registry.yarnpkg.com/pxt-core/-/pxt-core-5.37.83.tgz#75e4fee2500019d1a000d9c5829e75bdef5dd004" - integrity sha512-4HMV9Zkwu2MB6rdbZNK95pvIvORe/rVBQHs34Eby07wwtB2B4fac0Nnq83Y+zNLSzDd6Th51mXdKIrJjYxLo2w== +pxt-core@6.13.55: + version "6.13.55" + resolved "https://registry.yarnpkg.com/pxt-core/-/pxt-core-6.13.55.tgz#91532ad9f42eb78e7a16f11e2d273ce68579e440" + integrity sha512-y8JkH1pmNr1inWqvckY+dbDb1pOd6CeNIzEmi0XGHZ7tAU+0VgQdrQcgzpQty7ywOUrlx2Y9yY1gnqXo+EkTuw== dependencies: + "@microsoft/immersive-reader-sdk" "1.1.0" applicationinsights-js "^1.0.20" - bluebird "3.5.1" browserify "16.2.0" chai "^3.5.0" cssnano "4.1.10" @@ -3361,15 +3110,16 @@ pxt-core@^5.34.1: mocha "5.1.0" pngjs "3.4.0" postcss "6.0.21" + promise.prototype.finally "^3.1.2" puppeteer "^2.0.0" request "2.88.0" rimraf "2.5.4" rtlcss "2.2.1" sanitize-html "1.22.0" semantic-ui-less "2.2.14" - uglify-js "3.3.21" + terser "5.6.0" -pxt-core@^6.1.18: +pxt-core@^6.13.9: version "6.13.57" resolved "https://registry.yarnpkg.com/pxt-core/-/pxt-core-6.13.57.tgz#3b1f6e74c32840db6367b23dc27a5c8f901a9a9c" integrity sha512-1FE26mvBLCW5b83Hai7bxEo27MnysGfyVte6gUTjs2zfUw6wv7IA58WWTrxCT5Vs+rTOtva4UpN3K4j9hxsnNQ== @@ -3465,16 +3215,6 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -3497,7 +3237,7 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -3510,7 +3250,7 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -3702,16 +3442,6 @@ semantic-ui-less@2.2.14: dependencies: jquery x.* -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" @@ -3745,25 +3475,11 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - simple-concat@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -3837,7 +3553,7 @@ source-map@^0.5.3, source-map@~0.5.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -3928,23 +3644,6 @@ streamroller@^1.0.6: fs-extra "^7.0.1" lodash "^4.17.14" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -3980,21 +3679,7 @@ stringstream@~0.0.4: resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: +strip-json-comments@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -4062,27 +3747,6 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" -tar-fs@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" - integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - terser@5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.0.tgz#138cdf21c5e3100b1b3ddfddf720962f88badcd2" @@ -4206,14 +3870,6 @@ typescript@^3.7.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== -uglify-js@3.3.21: - version "3.3.21" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.21.tgz#851a34cbb31840ecb881968ed07dd3a61e7264a0" - integrity sha512-uy82472lH8tshK3jS3c5IFb5MmNKd/5qyBd0ih8sM42L3jWvxnE339U9gZU1zufnLVs98Stib9twq8dLm2XYCA== - dependencies: - commander "~2.15.0" - source-map "~0.6.1" - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -4285,15 +3941,6 @@ url@~0.11.0: punycode "1.3.2" querystring "0.2.0" -usb@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/usb/-/usb-1.7.1.tgz#d723223ec517b802c4d2082e31a4649c65c491c5" - integrity sha512-HTCfx6NnNRhv5y98t04Y8j2+A8dmQnEGxCMY2/zN/0gkiioLYfTZ5w/PEKlWRVUY+3qLe9xwRv9pHLkjQYNw/g== - dependencies: - bindings "^1.4.0" - node-addon-api "3.0.2" - prebuild-install "^5.3.3" - useragent@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" @@ -4379,15 +4026,6 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -webusb@^1.1.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/webusb/-/webusb-1.3.1.tgz#d11343ae10a0673050c1485c8bee4c96f138d51e" - integrity sha512-Z7JLoko7LHavfeuLteaT2B4+79EKME6EbTGw+Kg2iXCHNlQ2e57A5GZM6wd0uLeLuW+CnvCSV3ZP1u3l9Yxmgw== - dependencies: - "@types/node" "^8.0.54" - "@types/usb" "^1.5.1" - usb "^1.6.0" - which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -4399,11 +4037,6 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - which@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -4411,13 +4044,6 @@ which@^1.2.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" From c24d0589ef26d021b485921d58d004d7c1b1943f Mon Sep 17 00:00:00 2001 From: JoeBakalor Date: Mon, 19 Jul 2021 11:51:29 -0500 Subject: [PATCH 2/6] led, updated core --- .circleci/config.yml | 1 + libs/core---nrf52/led.cpp | 11 +++++++---- package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 326cbfa9..3b2aa351 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,6 +5,7 @@ machine: orbs: aws-ecr: circleci/aws-ecr@6.1.0 aws-ecs: circleci/aws-ecs@0.0.8 + aws-cli: circleci/aws-cli@2.0.3 defaults: &defaults working_directory: ~/pxt-texknikio diff --git a/libs/core---nrf52/led.cpp b/libs/core---nrf52/led.cpp index d382cd10..6ffc1fa5 100644 --- a/libs/core---nrf52/led.cpp +++ b/libs/core---nrf52/led.cpp @@ -1,20 +1,23 @@ #include "pxt.h" #include "pxtbase.h" +#include "TeknikioDevice.h" -namespace pxt { - TeknikioDevice bluebird; +extern TeknikioDevice bluebird; +namespace pxt { void initTeknikio() { bluebird.init(); } } +using namespace pxt; + + //% color=#7600A8 weight=101 icon="\uf205" namespace led { - - extern TeknikioDevice bluebird; + typedef uint32_t ImageLiteral_; /** * Draws an image on the LED screen. diff --git a/package.json b/package.json index 9c964021..1458f6c4 100755 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "react": "16.8.3", "semantic-ui-less": "2.2.14", "svgo": "^1.3.2", - "typescript": "^3.7.5" + "typescript": "3.7.5" }, "scripts": { "serve": "node node_modules/pxt-core/built/pxt.js serve", diff --git a/yarn.lock b/yarn.lock index d238b1ff..132c78b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3865,10 +3865,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.7.5: - version "3.9.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" - integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== +typescript@3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== ultron@~1.1.0: version "1.1.1" From 8a509a3f9220c421abac4b8e573727ddd085aae3 Mon Sep 17 00:00:00 2001 From: JoeBakalor Date: Tue, 20 Jul 2021 09:56:12 -0500 Subject: [PATCH 3/6] code cleanup --- libs/base/README.md | 5 - libs/base/advmath.cpp | 26 - libs/base/buffer.cpp | 422 ---- libs/base/buffer.ts | 453 ---- libs/base/configkeys.h | 478 ---- libs/base/console.ts | 138 -- libs/base/control.cpp | 103 - libs/base/control.ts | 185 -- libs/base/controlgc.cpp | 50 - libs/base/controlmessage.ts | 41 - libs/base/core.cpp | 2029 ----------------- libs/base/docs/blocks/pause-until.md | 53 - libs/base/docs/device/error-codes.md | 53 - libs/base/docs/reference/console.md | 13 - libs/base/docs/reference/console/log-value.md | 38 - libs/base/docs/reference/console/log.md | 33 - libs/base/docs/reference/control.md | 25 - libs/base/docs/reference/control/assert.md | 33 - .../reference/control/device-dal-version.md | 25 - .../reference/control/device-serial-number.md | 25 - libs/base/docs/reference/control/millis.md | 25 - libs/base/docs/reference/control/on-event.md | 93 - libs/base/docs/reference/control/panic.md | 37 - .../docs/reference/control/raise-event.md | 61 - libs/base/docs/reference/control/reset.md | 20 - .../reference/control/run-in-background.md | 3 - .../docs/reference/control/run-in-parallel.md | 75 - .../docs/reference/control/wait-for-event.md | 63 - .../docs/reference/control/wait-micros.md | 26 - libs/base/docs/reference/input.md | 53 - libs/base/docs/reference/loops/forever.md | 33 - libs/base/docs/reference/loops/pause.md | 31 - .../docs/reference/text/convert-to-text.md | 34 - libs/base/eventcontext.ts | 289 --- libs/base/fixed.ts | 75 - libs/base/forever.ts | 18 - libs/base/gc.cpp | 907 -------- libs/base/gcstats.ts | 40 - libs/base/interval.ts | 72 - libs/base/json.ts | 322 --- libs/base/loops.cpp | 27 - libs/base/math.ts | 83 - libs/base/ns.ts | 7 - libs/base/pause.ts | 19 - libs/base/perfcounters.ts | 13 - libs/base/poll.ts | 78 - libs/base/pxt.cpp | 518 ----- libs/base/pxt.json | 60 +- libs/base/pxtbase.h | 1220 ---------- libs/base/scheduling.ts | 56 - libs/base/shims.d.ts | 2 + libs/base/sim/cfg.ts | 20 - libs/base/sim/control.ts | 220 -- libs/base/sim/controlmessage.ts | 68 - libs/base/sim/core.ts | 14 - libs/base/sim/loops.ts | 4 - libs/base/sim/tsconfig.json | 15 - libs/base/templates.ts | 5 - libs/base/test.ts | 14 - libs/base/trig.cpp | 37 - libs/base/utfdecoder.ts | 83 - libs/core---nrf52/led.cpp | 2 - 62 files changed, 4 insertions(+), 9066 deletions(-) delete mode 100644 libs/base/README.md delete mode 100644 libs/base/advmath.cpp delete mode 100644 libs/base/buffer.cpp delete mode 100644 libs/base/buffer.ts delete mode 100644 libs/base/configkeys.h delete mode 100644 libs/base/console.ts delete mode 100644 libs/base/control.cpp delete mode 100644 libs/base/control.ts delete mode 100644 libs/base/controlgc.cpp delete mode 100644 libs/base/controlmessage.ts delete mode 100644 libs/base/core.cpp delete mode 100644 libs/base/docs/blocks/pause-until.md delete mode 100644 libs/base/docs/device/error-codes.md delete mode 100644 libs/base/docs/reference/console.md delete mode 100644 libs/base/docs/reference/console/log-value.md delete mode 100644 libs/base/docs/reference/console/log.md delete mode 100644 libs/base/docs/reference/control.md delete mode 100644 libs/base/docs/reference/control/assert.md delete mode 100644 libs/base/docs/reference/control/device-dal-version.md delete mode 100644 libs/base/docs/reference/control/device-serial-number.md delete mode 100644 libs/base/docs/reference/control/millis.md delete mode 100644 libs/base/docs/reference/control/on-event.md delete mode 100644 libs/base/docs/reference/control/panic.md delete mode 100644 libs/base/docs/reference/control/raise-event.md delete mode 100644 libs/base/docs/reference/control/reset.md delete mode 100644 libs/base/docs/reference/control/run-in-background.md delete mode 100644 libs/base/docs/reference/control/run-in-parallel.md delete mode 100644 libs/base/docs/reference/control/wait-for-event.md delete mode 100644 libs/base/docs/reference/control/wait-micros.md delete mode 100644 libs/base/docs/reference/input.md delete mode 100644 libs/base/docs/reference/loops/forever.md delete mode 100644 libs/base/docs/reference/loops/pause.md delete mode 100644 libs/base/docs/reference/text/convert-to-text.md delete mode 100644 libs/base/eventcontext.ts delete mode 100644 libs/base/fixed.ts delete mode 100644 libs/base/forever.ts delete mode 100644 libs/base/gc.cpp delete mode 100644 libs/base/gcstats.ts delete mode 100644 libs/base/interval.ts delete mode 100644 libs/base/json.ts delete mode 100644 libs/base/loops.cpp delete mode 100644 libs/base/math.ts delete mode 100644 libs/base/ns.ts delete mode 100644 libs/base/pause.ts delete mode 100644 libs/base/perfcounters.ts delete mode 100644 libs/base/poll.ts delete mode 100644 libs/base/pxt.cpp delete mode 100644 libs/base/pxtbase.h delete mode 100644 libs/base/scheduling.ts delete mode 100644 libs/base/sim/cfg.ts delete mode 100644 libs/base/sim/control.ts delete mode 100644 libs/base/sim/controlmessage.ts delete mode 100644 libs/base/sim/core.ts delete mode 100644 libs/base/sim/loops.ts delete mode 100644 libs/base/sim/tsconfig.json delete mode 100644 libs/base/templates.ts delete mode 100644 libs/base/test.ts delete mode 100644 libs/base/trig.cpp delete mode 100644 libs/base/utfdecoder.ts diff --git a/libs/base/README.md b/libs/base/README.md deleted file mode 100644 index d61a17da..00000000 --- a/libs/base/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# base - -The base library, shared by all C++ targets (not only Codal-based). - - diff --git a/libs/base/advmath.cpp b/libs/base/advmath.cpp deleted file mode 100644 index df2828b6..00000000 --- a/libs/base/advmath.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "pxtbase.h" - -using namespace std; - -#define SINGLE(op) return fromDouble(::op(toDouble(x))); - -namespace Math_ { - -//% -TNumber log2(TNumber x){SINGLE(log2)} -//% -TNumber exp(TNumber x){SINGLE(exp)} -//% -TNumber tanh(TNumber x){SINGLE(tanh)} -//% -TNumber sinh(TNumber x){SINGLE(sinh)} -//% -TNumber cosh(TNumber x){SINGLE(cosh)} -//% -TNumber atanh(TNumber x){SINGLE(atanh)} -//% -TNumber asinh(TNumber x){SINGLE(asinh)} -//% -TNumber acosh(TNumber x){SINGLE(acosh)} - -} \ No newline at end of file diff --git a/libs/base/buffer.cpp b/libs/base/buffer.cpp deleted file mode 100644 index cd8823ef..00000000 --- a/libs/base/buffer.cpp +++ /dev/null @@ -1,422 +0,0 @@ -#include "pxtbase.h" -#include - -using namespace std; - -//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte -namespace BufferMethods { -//% -uint8_t *getBytes(Buffer buf) { - return buf->data; -} - -//% -int getByte(Buffer buf, int off) { - if (buf && 0 <= off && off < buf->length) - return buf->data[off]; - return 0; -} - -//% -void setByte(Buffer buf, int off, int v) { - if (buf && 0 <= off && off < buf->length) - buf->data[off] = v; -} - -/** -* Reads an unsigned byte at a particular location -*/ -//% -int getUint8(Buffer buf, int off) { - return getByte(buf, off); -} - -/** - * Returns false when the buffer can be written to. - */ -//% -bool isReadOnly(Buffer buf) { - return buf->isReadOnly(); -} - -/** -* Writes an unsigned byte at a particular location -*/ -//% -void setUint8(Buffer buf, int off, int v) { - setByte(buf, off, v); -} - -int writeBuffer(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1) { - if (length < 0) - length = src->length; - - if (srcOffset < 0 || dstOffset < 0 || dstOffset > buf->length) - return -1; - - length = min(src->length - srcOffset, buf->length - dstOffset); - - if (length < 0) - return -1; - - if (buf == src) { - memmove(buf->data + dstOffset, src->data + srcOffset, length); - } else { - memcpy(buf->data + dstOffset, src->data + srcOffset, length); - } - - return 0; -} - -/** - * Write a number in specified format in the buffer. - */ -//% -void setNumber(Buffer buf, NumberFormat format, int offset, TNumber value) { - if (offset < 0) - return; - setNumberCore(buf->data + offset, buf->length - offset, format, value); -} - -/** - * Read a number in specified format from the buffer. - */ -//% -TNumber getNumber(Buffer buf, NumberFormat format, int offset) { - if (offset < 0) - return fromInt(0); - return getNumberCore(buf->data + offset, buf->length - offset, format); -} - -/** Returns the length of a Buffer object. */ -//% property -int length(Buffer s) { - return s->length; -} - -/** - * Fill (a fragment) of the buffer with given value. - */ -//% -void fill(Buffer buf, int value, int offset = 0, int length = -1) { - if (offset < 0 || offset > buf->length) - return; // DEVICE_INVALID_PARAMETER; - if (length < 0) - length = buf->length; - length = min(length, buf->length - offset); - memset(buf->data + offset, value, length); -} - -/** - * Return a copy of a fragment of a buffer. - */ -//% -Buffer slice(Buffer buf, int offset = 0, int length = -1) { - offset = min((int)buf->length, offset); - if (length < 0) - length = buf->length; - length = min(length, buf->length - offset); - return mkBuffer(buf->data + offset, length); -} - -/** - * Shift buffer left in place, with zero padding. - * @param offset number of bytes to shift; use negative value to shift right - * @param start start offset in buffer. Default is 0. - * @param length number of elements in buffer. If negative, length is set as the buffer length minus - * start. eg: -1 - */ -//% -void shift(Buffer buf, int offset, int start = 0, int length = -1) { - if (length < 0) - length = buf->length - start; - if (start < 0 || start + length > buf->length || start + length < start || length == 0 || - offset == 0 || offset == INT_MIN) - return; - if (offset <= -length || offset >= length) { - fill(buf, 0); - return; - } - - uint8_t *data = buf->data + start; - if (offset < 0) { - offset = -offset; - memmove(data + offset, data, length - offset); - memset(data, 0, offset); - } else { - length = length - offset; - memmove(data, data + offset, length); - memset(data + length, 0, offset); - } -} - -/** - * Convert a buffer to string assuming UTF8 encoding - */ -//% -String toString(Buffer buf) { - return mkString((char *)buf->data, buf->length); -} - -/** - * Convert a buffer to its hexadecimal representation. - */ -//% -String toHex(Buffer buf) { - const char *hex = "0123456789abcdef"; - auto res = mkStringCore(NULL, buf->length * 2); - for (int i = 0; i < buf->length; ++i) { - res->ascii.data[i << 1] = hex[buf->data[i] >> 4]; - res->ascii.data[(i << 1) + 1] = hex[buf->data[i] & 0xf]; - } - return res; -} - -/** - * Rotate buffer left in place. - * @param offset number of bytes to shift; use negative value to shift right - * @param start start offset in buffer. Default is 0. - * @param length number of elements in buffer. If negative, length is set as the buffer length minus - * start. eg: -1 - */ -//% -void rotate(Buffer buf, int offset, int start = 0, int length = -1) { - if (length < 0) - length = buf->length - start; - if (start < 0 || start + length > buf->length || start + length < start || length == 0 || - offset == 0 || offset == INT_MIN) - return; - - if (offset < 0) - offset += length << 8; // try to make it positive - offset %= length; - if (offset < 0) - offset += length; - - uint8_t *data = buf->data + start; - - uint8_t *n_first = data + offset; - uint8_t *first = data; - uint8_t *next = n_first; - uint8_t *last = data + length; - - while (first != next) { - uint8_t tmp = *first; - *first++ = *next; - *next++ = tmp; - if (next == last) { - next = n_first; - } else if (first == n_first) { - n_first = next; - } - } -} - -/** - * Write contents of `src` at `dstOffset` in current buffer. - */ -//% -void write(Buffer buf, int dstOffset, Buffer src) { - // srcOff and length not supported, we only do up to 4 args :/ - writeBuffer(buf, dstOffset, src, 0, -1); -} - -/** - * Compute k-bit FNV-1 non-cryptographic hash of the buffer. - */ -//% -uint32_t hash(Buffer buf, int bits) { - if (bits < 1) - return 0; - uint32_t h = hash_fnv1(buf->data, buf->length); - if (bits >= 32) - return h; - else - return ((h ^ (h >> bits)) & ((1 << bits) - 1)); -} - -} // namespace BufferMethods - -// The functions below are deprecated in control namespace, but they are referenced -// in Buffer namespaces via explicit shim=... -namespace control { -/** - * Create a new zero-initialized buffer. - * @param size number of bytes in the buffer - */ -//% deprecated=1 -Buffer createBuffer(int size) { - return mkBuffer(NULL, size); -} - - -/** - * Create a new buffer with UTF8-encoded string - * @param str the string to put in the buffer - */ -//% deprecated=1 -Buffer createBufferFromUTF8(String str) { -#if PXT_UTF8 - auto sz = toRealUTF8(str, NULL); - auto r = mkBuffer(NULL, sz); - toRealUTF8(str, r->data); - return r; -#else - return mkBuffer((const uint8_t *)str->getUTF8Data(), str->getUTF8Size()); -#endif -} -} // namespace control - -namespace pxt { -static int writeBytes(uint8_t *dst, uint8_t *src, int length, bool swapBytes, int szLeft) { - if (szLeft < length) { - return -1; - } - - if (swapBytes) { - uint8_t *p = dst + length; - for (int i = 0; i < length; ++i) - *--p = src[i]; - } else { - if (length == 4 && ((uintptr_t)dst & 3) == 0) - *(uint32_t *)dst = *(uint32_t *)src; - else if (length == 2 && ((uintptr_t)dst & 1) == 0) - *(uint16_t *)dst = *(uint16_t *)src; - else - memcpy(dst, src, length); - } - - return 0; -} - -static int readBytes(uint8_t *src, uint8_t *dst, int length, bool swapBytes, int szLeft) { - if (szLeft < length) { - memset(dst, 0, length); - return -1; - } - - if (swapBytes) { - uint8_t *p = src + length; - for (int i = 0; i < length; ++i) - dst[i] = *--p; - } else { - if (length == 4 && ((uintptr_t)src & 3) == 0) - *(uint32_t *)dst = *(uint32_t *)src; - else if (length == 2 && ((uintptr_t)src & 1) == 0) - *(uint16_t *)dst = *(uint16_t *)src; - else - memcpy(dst, src, length); - } - - return 0; -} - -void setNumberCore(uint8_t *buf, int szLeft, NumberFormat format, TNumber value) { - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - float f32; - double f64; - -// Assume little endian -#define WRITEBYTES(isz, swap, toInt) \ - isz = toInt(value); \ - writeBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ - break - - switch (format) { - case NumberFormat::Int8LE: - WRITEBYTES(i8, false, toInt); - case NumberFormat::UInt8LE: - WRITEBYTES(u8, false, toInt); - case NumberFormat::Int16LE: - WRITEBYTES(i16, false, toInt); - case NumberFormat::UInt16LE: - WRITEBYTES(u16, false, toInt); - case NumberFormat::Int32LE: - WRITEBYTES(i32, false, toInt); - case NumberFormat::UInt32LE: - WRITEBYTES(u32, false, toUInt); - - case NumberFormat::Int8BE: - WRITEBYTES(i8, true, toInt); - case NumberFormat::UInt8BE: - WRITEBYTES(u8, true, toInt); - case NumberFormat::Int16BE: - WRITEBYTES(i16, true, toInt); - case NumberFormat::UInt16BE: - WRITEBYTES(u16, true, toInt); - case NumberFormat::Int32BE: - WRITEBYTES(i32, true, toInt); - case NumberFormat::UInt32BE: - WRITEBYTES(u32, true, toUInt); - - case NumberFormat::Float32LE: - WRITEBYTES(f32, false, toFloat); - case NumberFormat::Float32BE: - WRITEBYTES(f32, true, toFloat); - case NumberFormat::Float64LE: - WRITEBYTES(f64, false, toDouble); - case NumberFormat::Float64BE: - WRITEBYTES(f64, true, toDouble); - } -} - -TNumber getNumberCore(uint8_t *buf, int szLeft, NumberFormat format) { - int8_t i8; - uint8_t u8; - int16_t i16; - uint16_t u16; - int32_t i32; - uint32_t u32; - float f32; - double f64; - -// Assume little endian -#define READBYTES(isz, swap, conv) \ - readBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \ - return conv(isz) - - switch (format) { - case NumberFormat::Int8LE: - READBYTES(i8, false, fromInt); - case NumberFormat::UInt8LE: - READBYTES(u8, false, fromInt); - case NumberFormat::Int16LE: - READBYTES(i16, false, fromInt); - case NumberFormat::UInt16LE: - READBYTES(u16, false, fromInt); - case NumberFormat::Int32LE: - READBYTES(i32, false, fromInt); - case NumberFormat::UInt32LE: - READBYTES(u32, false, fromUInt); - - case NumberFormat::Int8BE: - READBYTES(i8, true, fromInt); - case NumberFormat::UInt8BE: - READBYTES(u8, true, fromInt); - case NumberFormat::Int16BE: - READBYTES(i16, true, fromInt); - case NumberFormat::UInt16BE: - READBYTES(u16, true, fromInt); - case NumberFormat::Int32BE: - READBYTES(i32, true, fromInt); - case NumberFormat::UInt32BE: - READBYTES(u32, true, fromUInt); - - case NumberFormat::Float32LE: - READBYTES(f32, false, fromFloat); - case NumberFormat::Float32BE: - READBYTES(f32, true, fromFloat); - case NumberFormat::Float64LE: - READBYTES(f64, false, fromDouble); - case NumberFormat::Float64BE: - READBYTES(f64, true, fromDouble); - } - - return 0; -} -} // namespace pxt diff --git a/libs/base/buffer.ts b/libs/base/buffer.ts deleted file mode 100644 index 60649a11..00000000 --- a/libs/base/buffer.ts +++ /dev/null @@ -1,453 +0,0 @@ -namespace pins { - //% deprecated=1 - export function sizeOf(format: NumberFormat) { - return Buffer.sizeOfNumberFormat(format) - } - - //% deprecated=1 - export function createBufferFromArray(bytes: number[]) { - return Buffer.fromArray(bytes) - } - - //% deprecated=1 - export function packedSize(format: string) { - return Buffer.packedSize(format) - } - - //% deprecated=1 - export function packBuffer(format: string, nums: number[]) { - return Buffer.pack(format, nums) - } - - //% deprecated=1 - export function packIntoBuffer(format: string, buf: Buffer, offset: number, nums: number[]) { - buf.packAt(offset, format, nums) - } - - //% deprecated=1 - export function unpackBuffer(format: string, buf: Buffer, offset = 0) { - return buf.unpack(format, offset) - } - - //% deprecated=1 - export function concatBuffers(bufs: Buffer[]) { - return Buffer.concat(bufs) - } -} - -// see http://msgpack.org/ for the spec -// it currently only implements numbers and their sequances -// once we handle any type and typeof expressions we can do more - -namespace msgpack { - function tagFormat(tag: number) { - switch (tag) { - case 0xCB: return NumberFormat.Float64BE - case 0xCC: return NumberFormat.UInt8BE - case 0xCD: return NumberFormat.UInt16BE - case 0xCE: return NumberFormat.UInt32BE - case 0xD0: return NumberFormat.Int8BE - case 0xD1: return NumberFormat.Int16BE - case 0xD2: return NumberFormat.Int32BE - default: - return null - } - } - - function packNumberCore(buf: Buffer, offset: number, num: number) { - let tag = 0xCB - if (num == (num << 0) || num == (num >>> 0)) { - if (-31 <= num && num <= 127) { - if (buf) buf[offset] = num - return 1 - } else if (0 <= num) { - if (num <= 0xff) { - tag = 0xCC - } else if (num <= 0xffff) { - tag = 0xCD - } else { - tag = 0xCE - } - } else { - if (-0x7f <= num) { - tag = 0xD0 - } else if (-0x7fff <= num) { - tag = 0xD1 - } else { - tag = 0xD2 - } - } - } - let fmt = tagFormat(tag) - if (buf) { - buf[offset] = tag - buf.setNumber(fmt, offset + 1, num) - } - return pins.sizeOf(fmt) + 1 - } - - /** - * Unpacks a buffer into a number array. - */ - export function unpackNumberArray(buf: Buffer, offset = 0): number[] { - let res: number[] = [] - - while (offset < buf.length) { - let fmt = tagFormat(buf[offset++]) - if (fmt === null) { - let v = buf.getNumber(NumberFormat.Int8BE, offset - 1) - if (-31 <= v && v <= 127) - res.push(v) - else - return null - } else { - res.push(buf.getNumber(fmt, offset)) - offset += pins.sizeOf(fmt) - } - // padding at the end - while (buf[offset] === 0xc1) offset++; - } - - return res - } - - /** - * Pack a number array into a buffer. - * @param nums the numbers to be packed - */ - export function packNumberArray(nums: number[]): Buffer { - let off = 0 - for (let n of nums) { - off += packNumberCore(null, off, n) - } - let buf = Buffer.create(off) - off = 0 - for (let n of nums) { - off += packNumberCore(buf, off, n) - } - return buf - } -} - -namespace helpers { - export function bufferConcat(a: Buffer, b: Buffer) { - const r = Buffer.create(a.length + b.length) - r.write(0, a) - r.write(a.length, b) - return r - } - - export function bufferEquals(l: Buffer, r: Buffer) { - if (!l || !r) return !!l == !!r; - if (l.length != r.length) return false; - for (let i = 0; i < l.length; ++i) { - if (l[i] != r[i]) - return false; - } - return true; - } - - export function bufferIndexOf(a: Buffer, b: Buffer) { - for (let i = 0; i <= a.length - b.length; ++i) { - if (a[i] == b[0]) { - let j = 0 - while (j < b.length) { - if (a[i + j] != b[j]) - break - j++ - } - if (j >= b.length) - return i - } - } - return -1 - } - - export function bufferUnpack(buf: Buffer, format: string, offset?: number) { - if (!offset) offset = 0 - let res: number[] = [] - Buffer.__packUnpackCore(format, res, buf, false, offset) - return res - } - - export function bufferPackAt(buf: Buffer, offset: number, format: string, nums: number[]) { - Buffer.__packUnpackCore(format, nums, buf, true, offset) - } - - export function bufferChunked(buf: Buffer, maxBytes: number) { - if (buf.length <= maxBytes) return [buf] - else { - const r: Buffer[] = [] - for (let i = 0; i < buf.length; i += maxBytes) - r.push(buf.slice(i, maxBytes)) - return r - } - } - - export function bufferToArray(buf: Buffer, format: NumberFormat) { - const sz = Buffer.sizeOfNumberFormat(format) - const len = buf.length - sz - const r: number[] = [] - for (let i = 0; i <= len; i += sz) - r.push(buf.getNumber(format, i)) - return r - } -} - -interface Buffer { - [index: number]: number; - - /** - * Return concatenation of current buffer and the given buffer - */ - //% helper=bufferConcat - concat(other: Buffer): Buffer; - - /** - * Return position of other buffer in current buffer - */ - //% helper=bufferIndexOf - indexOf(other: Buffer): number; - - /** - * Reads numbers from the buffer according to the format - */ - //% helper=bufferUnpack - unpack(format: string, offset?: number): number[]; - - /** - * Writes numbers to the buffer according to the format - */ - //% helper=bufferPackAt - packAt(offset: number, format: string, nums: number[]): void; - - /** - * Returns true if this and the other buffer hold the same data - */ - //% helper=bufferEquals - equals(other: Buffer): boolean; - - /** - * Splits buffer into parts no larger than specified - */ - //% helper=bufferChunked - chunked(maxSize: number): Buffer[]; - - - /** - * Read contents of buffer as an array in specified format - */ - //% helper=bufferToArray - toArray(format: NumberFormat): number[]; - - // rest defined in buffer.cpp -} - -namespace Buffer { - /** - * Allocate a new buffer. - * @param size number of bytes in the buffer - */ - //% shim=control::createBuffer - export declare function create(size: number): Buffer; - - /** - * Create a new buffer, decoding a hex string - */ - export function fromHex(hex: string) { - const hexStr = "0123456789abcdef" - const res = Buffer.create(hex.length >> 1) - hex = hex.toLowerCase() - for (let i = 0; i < hex.length; i += 2) { - const p0 = hexStr.indexOf(hex.charAt(i)) - const p1 = hexStr.indexOf(hex.charAt(i + 1)) - if (p0 < 0 || p1 < 0) - throw "Invalid hex" - res[i >> 1] = (p0 << 4) | p1 - } - return res - } - - /** - * Create a new buffer with UTF8-encoded string - * @param str the string to put in the buffer - */ - //% shim=control::createBufferFromUTF8 - export declare function fromUTF8(str: string): Buffer; - - function chunkLen(s: string, off: number, maxlen: number) { - let L = Math.idiv(maxlen, 3) - let R = maxlen - - if (fromUTF8(s.slice(off, off + R)).length <= maxlen) - return R - - while (L < R) { - const m = (L + R) >> 1 - if (m == L) - break - const ll = fromUTF8(s.slice(off, off + m)).length - if (ll <= maxlen) - L = m - else - R = m - } - - return L - } - - export function chunkedFromUTF8(str: string, maxBytes: number) { - if (maxBytes < 3) - throw "Oops" - const chunks: Buffer[] = [] - let pos = 0 - while (pos < str.length) { - const len = chunkLen(str, pos, maxBytes) - chunks.push(fromUTF8(str.slice(pos, pos + len))) - pos += len - } - return chunks - } - - /** - * Create a new buffer initialized to bytes from given array. - * @param bytes data to initialize with - */ - export function fromArray(bytes: number[]) { - let buf = Buffer.create(bytes.length) - for (let i = 0; i < bytes.length; ++i) - buf[i] = bytes[i] - return buf - } - - /** - * Concatenates all buffers in the list - */ - export function concat(buffers: Buffer[]) { - let len = 0 - for (let b of buffers) - len += b.length - const r = Buffer.create(len) - len = 0 - for (let b of buffers) { - r.write(len, b) - len += b.length - } - return r - } - - // Python-like packing, see https://docs.python.org/3/library/struct.html - - export function packedSize(format: string) { - return __packUnpackCore(format, null, null, true) - } - - export function pack(format: string, nums: number[]) { - let buf = Buffer.create(packedSize(format)) - __packUnpackCore(format, nums, buf, true) - return buf - } - - function getFormat(pychar: string, isBig: boolean) { - switch (pychar) { - case 'B': - return NumberFormat.UInt8LE - case 'b': - return NumberFormat.Int8LE - case 'H': - return isBig ? NumberFormat.UInt16BE : NumberFormat.UInt16LE - case 'h': - return isBig ? NumberFormat.Int16BE : NumberFormat.Int16LE - case 'I': - case 'L': - return isBig ? NumberFormat.UInt32BE : NumberFormat.UInt32LE - case 'i': - case 'l': - return isBig ? NumberFormat.Int32BE : NumberFormat.Int32LE - case 'f': - return isBig ? NumberFormat.Float32BE : NumberFormat.Float32LE - case 'd': - return isBig ? NumberFormat.Float64BE : NumberFormat.Float64LE - default: - return null as NumberFormat - } - } - - function isDigit(ch: string) { - const code = ch.charCodeAt(0) - return 0x30 <= code && code <= 0x39 - } - - export function __packUnpackCore(format: string, nums: number[], buf: Buffer, isPack: boolean, off = 0) { - let isBig = false - let idx = 0 - for (let i = 0; i < format.length; ++i) { - switch (format[i]) { - case ' ': - case '<': - case '=': - isBig = false - break - case '>': - case '!': - isBig = true - break - default: - const i0 = i - while (isDigit(format[i])) i++ - let reps = 1 - if (i0 != i) - reps = parseInt(format.slice(i0, i)) - if (format[i] == 'x') - off += reps - else - while (reps--) { - let fmt = getFormat(format[i], isBig) - if (fmt === null) { - control.fail("Unsupported format character: " + format[i]) - } else { - if (buf) { - if (isPack) - buf.setNumber(fmt, off, nums[idx++]) - else - nums.push(buf.getNumber(fmt, off)) - } - - off += sizeOfNumberFormat(fmt) - } - } - break - } - } - return off - } - - /** - * Get the size in bytes of specified number format. - */ - export function sizeOfNumberFormat(format: NumberFormat) { - switch (format) { - case NumberFormat.Int8LE: - case NumberFormat.UInt8LE: - case NumberFormat.Int8BE: - case NumberFormat.UInt8BE: - return 1; - case NumberFormat.Int16LE: - case NumberFormat.UInt16LE: - case NumberFormat.Int16BE: - case NumberFormat.UInt16BE: - return 2; - case NumberFormat.Int32LE: - case NumberFormat.Int32BE: - case NumberFormat.UInt32BE: - case NumberFormat.UInt32LE: - case NumberFormat.Float32BE: - case NumberFormat.Float32LE: - return 4; - case NumberFormat.Float64BE: - case NumberFormat.Float64LE: - return 8; - } - return 0; - } -} diff --git a/libs/base/configkeys.h b/libs/base/configkeys.h deleted file mode 100644 index ba9544cb..00000000 --- a/libs/base/configkeys.h +++ /dev/null @@ -1,478 +0,0 @@ -#ifndef __PXT_CONFIGKEYS_H -#define __PXT_CONFIGKEYS_H - -// used by pins.cpp to mask off the pin name from any config -// lower 16 pins of value are the pin name -#define CFG_PIN_NAME_MSK 0x0000ffff -// upper 16 bits of value is any configuration of the pin. -#define CFG_PIN_CONFIG_MSK 0xffff0000 - -// begin optional pin configurations -#define CFG_PIN_CONFIG_ACTIVE_LO 0x10000 - - -#define CFG_MAGIC0 0x1e9e10f1 -#define CFG_MAGIC1 0x20227a79 - -// these define keys for getConfig() function -#define CFG_PIN_ACCELEROMETER_INT 1 -#define CFG_PIN_ACCELEROMETER_SCL 2 -#define CFG_PIN_ACCELEROMETER_SDA 3 -#define CFG_PIN_BTN_A 4 -#define CFG_PIN_BTN_B 5 -#define CFG_PIN_BTN_SLIDE 6 -#define CFG_PIN_DOTSTAR_CLOCK 7 -#define CFG_PIN_DOTSTAR_DATA 8 -#define CFG_PIN_FLASH_CS 9 -#define CFG_PIN_FLASH_MISO 10 -#define CFG_PIN_FLASH_MOSI 11 -#define CFG_PIN_FLASH_SCK 12 -#define CFG_PIN_LED 13 -#define CFG_PIN_LIGHT 14 -#define CFG_PIN_MICROPHONE 15 -#define CFG_PIN_MIC_CLOCK 16 -#define CFG_PIN_MIC_DATA 17 -#define CFG_PIN_MISO 18 -#define CFG_PIN_MOSI 19 -// the preferred pin to drive an external neopixel strip -#define CFG_PIN_NEOPIXEL 20 -#define CFG_PIN_RX 21 -#define CFG_PIN_RXLED 22 -#define CFG_PIN_SCK 23 -#define CFG_PIN_SCL 24 -#define CFG_PIN_SDA 25 -#define CFG_PIN_SPEAKER_AMP 26 -#define CFG_PIN_TEMPERATURE 27 -#define CFG_PIN_TX 28 -#define CFG_PIN_TXLED 29 -#define CFG_PIN_IR_OUT 30 -#define CFG_PIN_IR_IN 31 -#define CFG_PIN_DISPLAY_SCK 32 -#define CFG_PIN_DISPLAY_MISO 33 -#define CFG_PIN_DISPLAY_MOSI 34 -#define CFG_PIN_DISPLAY_CS 35 -#define CFG_PIN_DISPLAY_DC 36 -#define CFG_DISPLAY_WIDTH 37 -#define CFG_DISPLAY_HEIGHT 38 -#define CFG_DISPLAY_CFG0 39 -#define CFG_DISPLAY_CFG1 40 -#define CFG_DISPLAY_CFG2 41 -#define CFG_DISPLAY_CFG3 42 -#define CFG_PIN_DISPLAY_RST 43 -#define CFG_PIN_DISPLAY_BL 44 -#define CFG_PIN_SERVO_1 45 -#define CFG_PIN_SERVO_2 46 -#define CFG_PIN_BTN_LEFT 47 -#define CFG_PIN_BTN_RIGHT 48 -#define CFG_PIN_BTN_UP 49 -#define CFG_PIN_BTN_DOWN 50 -#define CFG_PIN_BTN_MENU 51 -#define CFG_PIN_LED_R 52 -#define CFG_PIN_LED_G 53 -#define CFG_PIN_LED_B 54 -#define CFG_PIN_LED1 55 -#define CFG_PIN_LED2 56 -#define CFG_PIN_LED3 57 -#define CFG_PIN_LED4 58 -#define CFG_SPEAKER_VOLUME 59 - -#define CFG_PIN_JACK_TX 60 -#define CFG_PIN_JACK_SENSE 61 -#define CFG_PIN_JACK_HPEN 62 -#define CFG_PIN_JACK_BZEN 63 -#define CFG_PIN_JACK_PWREN 64 -#define CFG_PIN_JACK_SND 65 -#define CFG_PIN_JACK_BUSLED 66 -#define CFG_PIN_JACK_COMMLED 67 - -#define CFG_PIN_BTN_SOFT_RESET 69 -#define CFG_ACCELEROMETER_TYPE 70 -#define CFG_PIN_BTNMX_LATCH 71 -#define CFG_PIN_BTNMX_CLOCK 72 -#define CFG_PIN_BTNMX_DATA 73 -#define CFG_PIN_BTN_MENU2 74 -#define CFG_PIN_BATTSENSE 75 -#define CFG_PIN_VIBRATION 76 -#define CFG_PIN_PWREN 77 -#define CFG_DISPLAY_TYPE 78 - -#define CFG_PIN_ROTARY_ENCODER_A 79 -#define CFG_PIN_ROTARY_ENCODER_B 80 - -#define CFG_ACCELEROMETER_SPACE 81 - -#define CFG_PIN_WIFI_MOSI 82 -#define CFG_PIN_WIFI_MISO 83 -#define CFG_PIN_WIFI_SCK 84 -#define CFG_PIN_WIFI_TX 85 -#define CFG_PIN_WIFI_RX 86 -#define CFG_PIN_WIFI_CS 87 -#define CFG_PIN_WIFI_BUSY 88 -#define CFG_PIN_WIFI_RESET 89 -#define CFG_PIN_WIFI_GPIO0 90 -#define CFG_PIN_WIFI_AT_TX 91 -#define CFG_PIN_WIFI_AT_RX 92 - -#define CFG_PIN_USB_POWER 93 - -// default I2C address -#define ACCELEROMETER_TYPE_LIS3DH 0x32 -#define ACCELEROMETER_TYPE_LIS3DH_ALT 0x30 -#define ACCELEROMETER_TYPE_MMA8453 0x38 -#define ACCELEROMETER_TYPE_FXOS8700 0x3C -#define ACCELEROMETER_TYPE_MMA8653 0x3A -#define ACCELEROMETER_TYPE_MSA300 0x4C -#define ACCELEROMETER_TYPE_MPU6050 0x68 - -#define DISPLAY_TYPE_ST7735 7735 -#define DISPLAY_TYPE_ILI9341 9341 -#define DISPLAY_TYPE_SMART 4242 - -#define CFG_PIN_A0 100 -#define CFG_PIN_A1 101 -#define CFG_PIN_A2 102 -#define CFG_PIN_A3 103 -#define CFG_PIN_A4 104 -#define CFG_PIN_A5 105 -#define CFG_PIN_A6 106 -#define CFG_PIN_A7 107 -#define CFG_PIN_A8 108 -#define CFG_PIN_A9 109 -#define CFG_PIN_A10 110 -#define CFG_PIN_A11 111 -#define CFG_PIN_A12 112 -#define CFG_PIN_A13 113 -#define CFG_PIN_A14 114 -#define CFG_PIN_A15 115 -#define CFG_PIN_A16 116 -#define CFG_PIN_A17 117 -#define CFG_PIN_A18 118 -#define CFG_PIN_A19 119 -#define CFG_PIN_A20 120 -#define CFG_PIN_A21 121 -#define CFG_PIN_A22 122 -#define CFG_PIN_A23 123 -#define CFG_PIN_A24 124 -#define CFG_PIN_A25 125 -#define CFG_PIN_A26 126 -#define CFG_PIN_A27 127 -#define CFG_PIN_A28 128 -#define CFG_PIN_A29 129 -#define CFG_PIN_A30 130 -#define CFG_PIN_A31 131 - -#define CFG_PIN_D0 150 -#define CFG_PIN_D1 151 -#define CFG_PIN_D2 152 -#define CFG_PIN_D3 153 -#define CFG_PIN_D4 154 -#define CFG_PIN_D5 155 -#define CFG_PIN_D6 156 -#define CFG_PIN_D7 157 -#define CFG_PIN_D8 158 -#define CFG_PIN_D9 159 -#define CFG_PIN_D10 160 -#define CFG_PIN_D11 161 -#define CFG_PIN_D12 162 -#define CFG_PIN_D13 163 -#define CFG_PIN_D14 164 -#define CFG_PIN_D15 165 -#define CFG_PIN_D16 166 -#define CFG_PIN_D17 167 -#define CFG_PIN_D18 168 -#define CFG_PIN_D19 169 -#define CFG_PIN_D20 170 -#define CFG_PIN_D21 171 -#define CFG_PIN_D22 172 -#define CFG_PIN_D23 173 -#define CFG_PIN_D24 174 -#define CFG_PIN_D25 175 -#define CFG_PIN_D26 176 -#define CFG_PIN_D27 177 -#define CFG_PIN_D28 178 -#define CFG_PIN_D29 179 -#define CFG_PIN_D30 180 -#define CFG_PIN_D31 181 - -#define CFG_NUM_NEOPIXELS 200 -#define CFG_NUM_DOTSTARS 201 -#define CFG_DEFAULT_BUTTON_MODE 202 -#define CFG_SWD_ENABLED 203 -#define CFG_FLASH_BYTES 204 -#define CFG_RAM_BYTES 205 -#define CFG_SYSTEM_HEAP_BYTES 206 -#define CFG_LOW_MEM_SIMULATION_KB 207 -#define CFG_BOOTLOADER_BOARD_ID 208 -#define CFG_UF2_FAMILY 209 -#define CFG_PINS_PORT_SIZE 210 -#define CFG_BOOTLOADER_PROTECTION 211 -#define CFG_POWER_DEEPSLEEP_TIMEOUT 212 -#define CFG_ANALOG_BUTTON_THRESHOLD 213 -#define CFG_CPU_MHZ 214 -#define CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS 215 -#define CFG_ANALOG_JOYSTICK_MIN 216 -#define CFG_ANALOG_JOYSTICK_MAX 217 -#define CFG_TIMERS_TO_USE 218 -// configs to specify the onboard (built-in) dotstar or neopixel strips -// some boards have a combination of dotstar, neopixel strips like neotrellis -#define CFG_PIN_ONBOARD_DOTSTAR_CLOCK 219 -#define CFG_PIN_ONBOARD_DOTSTAR_DATA 220 -#define CFG_NUM_ONBOARD_DOTSTARS 221 -#define CFG_PIN_ONBOARD_NEOPIXEL 222 -#define CFG_NUM_ONBOARD_NEOPIXELS 223 - -#define CFG_MATRIX_KEYPAD_MESSAGE_ID 239 -#define CFG_NUM_MATRIX_KEYPAD_ROWS 240 -#define CFG_PIN_MATRIX_KEYPAD_ROW0 241 -#define CFG_PIN_MATRIX_KEYPAD_ROW1 242 -#define CFG_PIN_MATRIX_KEYPAD_ROW2 243 -#define CFG_PIN_MATRIX_KEYPAD_ROW3 244 -#define CFG_PIN_MATRIX_KEYPAD_ROW4 245 -#define CFG_PIN_MATRIX_KEYPAD_ROW5 246 -#define CFG_PIN_MATRIX_KEYPAD_ROW6 247 -#define CFG_PIN_MATRIX_KEYPAD_ROW7 248 -#define CFG_NUM_MATRIX_KEYPAD_COLS 250 -#define CFG_PIN_MATRIX_KEYPAD_COL0 251 -#define CFG_PIN_MATRIX_KEYPAD_COL1 252 -#define CFG_PIN_MATRIX_KEYPAD_COL2 253 -#define CFG_PIN_MATRIX_KEYPAD_COL3 254 -#define CFG_PIN_MATRIX_KEYPAD_COL4 255 -#define CFG_PIN_MATRIX_KEYPAD_COL5 256 -#define CFG_PIN_MATRIX_KEYPAD_COL6 257 -#define CFG_PIN_MATRIX_KEYPAD_COL7 258 - -#define CFG_PIN_B0 300 -#define CFG_PIN_B1 301 -#define CFG_PIN_B2 302 -#define CFG_PIN_B3 303 -#define CFG_PIN_B4 304 -#define CFG_PIN_B5 305 -#define CFG_PIN_B6 306 -#define CFG_PIN_B7 307 -#define CFG_PIN_B8 308 -#define CFG_PIN_B9 309 -#define CFG_PIN_B10 310 -#define CFG_PIN_B11 311 -#define CFG_PIN_B12 312 -#define CFG_PIN_B13 313 -#define CFG_PIN_B14 314 -#define CFG_PIN_B15 315 -#define CFG_PIN_B16 316 -#define CFG_PIN_B17 317 -#define CFG_PIN_B18 318 -#define CFG_PIN_B19 319 -#define CFG_PIN_B20 320 -#define CFG_PIN_B21 321 -#define CFG_PIN_B22 322 -#define CFG_PIN_B23 323 -#define CFG_PIN_B24 324 -#define CFG_PIN_B25 325 -#define CFG_PIN_B26 326 -#define CFG_PIN_B27 327 -#define CFG_PIN_B28 328 -#define CFG_PIN_B29 329 -#define CFG_PIN_B30 330 -#define CFG_PIN_B31 331 - -#define CFG_PIN_C0 350 -#define CFG_PIN_C1 351 -#define CFG_PIN_C2 352 -#define CFG_PIN_C3 353 -#define CFG_PIN_C4 354 -#define CFG_PIN_C5 355 -#define CFG_PIN_C6 356 -#define CFG_PIN_C7 357 -#define CFG_PIN_C8 358 -#define CFG_PIN_C9 359 -#define CFG_PIN_C10 360 -#define CFG_PIN_C11 361 -#define CFG_PIN_C12 362 -#define CFG_PIN_C13 363 -#define CFG_PIN_C14 364 -#define CFG_PIN_C15 365 -#define CFG_PIN_C16 366 -#define CFG_PIN_C17 367 -#define CFG_PIN_C18 368 -#define CFG_PIN_C19 369 -#define CFG_PIN_C20 370 -#define CFG_PIN_C21 371 -#define CFG_PIN_C22 372 -#define CFG_PIN_C23 373 -#define CFG_PIN_C24 374 -#define CFG_PIN_C25 375 -#define CFG_PIN_C26 376 -#define CFG_PIN_C27 377 -#define CFG_PIN_C28 378 -#define CFG_PIN_C29 379 -#define CFG_PIN_C30 380 -#define CFG_PIN_C31 381 - -#define CFG_PIN_P0 400 -#define CFG_PIN_P1 401 -#define CFG_PIN_P2 402 -#define CFG_PIN_P3 403 -#define CFG_PIN_P4 404 -#define CFG_PIN_P5 405 -#define CFG_PIN_P6 406 -#define CFG_PIN_P7 407 -#define CFG_PIN_P8 408 -#define CFG_PIN_P9 409 -#define CFG_PIN_P10 410 -#define CFG_PIN_P11 411 -#define CFG_PIN_P12 412 -#define CFG_PIN_P13 413 -#define CFG_PIN_P14 414 -#define CFG_PIN_P15 415 -#define CFG_PIN_P16 416 -#define CFG_PIN_P17 417 -#define CFG_PIN_P18 418 -#define CFG_PIN_P19 419 -#define CFG_PIN_P20 420 -#define CFG_PIN_P21 421 -#define CFG_PIN_P22 422 -#define CFG_PIN_P23 423 -#define CFG_PIN_P24 424 -#define CFG_PIN_P25 425 -#define CFG_PIN_P26 426 -#define CFG_PIN_P27 427 -#define CFG_PIN_P28 428 -#define CFG_PIN_P29 429 -#define CFG_PIN_P30 430 -#define CFG_PIN_P31 431 -#define CFG_PIN_P32 432 -#define CFG_PIN_P33 433 -#define CFG_PIN_P34 434 -#define CFG_PIN_P35 435 -#define CFG_PIN_P36 436 -#define CFG_PIN_P37 437 -#define CFG_PIN_P38 438 -#define CFG_PIN_P39 439 -#define CFG_PIN_P40 440 -#define CFG_PIN_P41 441 -#define CFG_PIN_P42 442 -#define CFG_PIN_P43 443 -#define CFG_PIN_P44 444 -#define CFG_PIN_P45 445 -#define CFG_PIN_P46 446 -#define CFG_PIN_P47 447 -#define CFG_PIN_P48 448 -#define CFG_PIN_P49 449 -#define CFG_PIN_P50 450 -#define CFG_PIN_P51 451 -#define CFG_PIN_P52 452 -#define CFG_PIN_P53 453 -#define CFG_PIN_P54 454 -#define CFG_PIN_P55 455 -#define CFG_PIN_P56 456 -#define CFG_PIN_P57 457 -#define CFG_PIN_P58 458 -#define CFG_PIN_P59 459 -#define CFG_PIN_P60 460 -#define CFG_PIN_P61 461 -#define CFG_PIN_P62 462 -#define CFG_PIN_P63 463 - -#define CFG_PIN_LORA_MISO 1001 -#define CFG_PIN_LORA_MOSI 1002 -#define CFG_PIN_LORA_SCK 1003 -#define CFG_PIN_LORA_CS 1004 -#define CFG_PIN_LORA_BOOT 1005 -#define CFG_PIN_LORA_RESET 1006 -#define CFG_PIN_IRRXLED 1007 -#define CFG_PIN_IRTXLED 1008 -#define CFG_PIN_LCD_RESET 1009 -#define CFG_PIN_LCD_ENABLE 1010 -#define CFG_PIN_LCD_DATALINE4 1011 -#define CFG_PIN_LCD_DATALINE5 1012 -#define CFG_PIN_LCD_DATALINE6 1013 -#define CFG_PIN_LCD_DATALINE7 1014 -#define CFG_NUM_LCD_COLUMNS 1015 -#define CFG_NUM_LCD_ROWS 1016 - -//RoboHAT MM1 pinout -#define CFG_PIN_RCC0 1017 -#define CFG_PIN_RCC1 1018 -#define CFG_PIN_RCC2 1019 -#define CFG_PIN_RCC3 1020 -#define CFG_PIN_RCC4 1021 -#define CFG_PIN_RCC5 1022 -#define CFG_PIN_RCC6 1023 -#define CFG_PIN_RCC7 1024 -#define CFG_PIN_SERVO0 1025 -#define CFG_PIN_SERVO1 1026 -#define CFG_PIN_SERVO2 1027 -#define CFG_PIN_SERVO3 1028 -#define CFG_PIN_SERVO4 1029 -#define CFG_PIN_SERVO5 1030 -#define CFG_PIN_SERVO6 1031 -#define CFG_PIN_SERVO7 1032 -#define CFG_PIN_SERVO8 1033 -#define CFG_PIN_PI_TX 1034 -#define CFG_PIN_PI_RX 1035 -#define CFG_PIN_GPS_SDA 1036 -#define CFG_PIN_GPS_SCL 1037 -#define CFG_PIN_GPS_TX 1038 -#define CFG_PIN_GPS_RX 1039 -#define CFG_PIN_GROVE0 1040 -#define CFG_PIN_GROVE1 1041 -#define CFG_PIN_SS 1042 - -// Adafruit Grand Central M4 -#define CFG_PIN_D33 183 -#define CFG_PIN_D34 184 -#define CFG_PIN_D35 185 -#define CFG_PIN_D36 186 -#define CFG_PIN_D37 187 -#define CFG_PIN_D38 188 -#define CFG_PIN_D39 189 -#define CFG_PIN_D40 190 -#define CFG_PIN_D41 191 -#define CFG_PIN_D42 192 -#define CFG_PIN_D43 193 -#define CFG_PIN_D44 194 -#define CFG_PIN_D45 195 -#define CFG_PIN_D46 196 -#define CFG_PIN_D47 197 -#define CFG_PIN_D48 198 -#define CFG_PIN_D49 199 -#define CFG_PIN_D50 259 -#define CFG_PIN_D51 260 -#define CFG_PIN_D52 261 -#define CFG_PIN_D53 262 - -#define CFG_PIN_TX1 263 -#define CFG_PIN_TX2 264 -#define CFG_PIN_TX3 265 -#define CFG_PIN_RX1 266 -#define CFG_PIN_RX2 267 -#define CFG_PIN_RX3 268 -#define CFG_PIN_SCL1 269 -#define CFG_PIN_SDA1 270 -#define CFG_PIN_PCC_D0 271 -#define CFG_PIN_PCC_D1 272 -#define CFG_PIN_PCC_D2 273 -#define CFG_PIN_PCC_D3 274 -#define CFG_PIN_PCC_D4 275 -#define CFG_PIN_PCC_D5 276 -#define CFG_PIN_PCC_D6 277 -#define CFG_PIN_PCC_D7 278 -#define CFG_PIN_PCC_D8 279 -#define CFG_PIN_PCC_D9 280 -#define CFG_PIN_PCC_D10 281 -#define CFG_PIN_PCC_D11 282 -#define CFG_PIN_PCC_D12 283 -#define CFG_PIN_PCC_D13 284 -#define CFG_PIN_CC_DEN1 285 -#define CFG_PIN_CC_DEN2 286 -#define CFG_PIN_CC_CLK 287 -#define CFG_PIN_XCC_CLK 288 - - -#define CFG_PIN_JDPWR_PRE_SENSE 1100 -#define CFG_PIN_JDPWR_GND_SENSE 1101 -#define CFG_PIN_JDPWR_PULSE 1102 -#define CFG_PIN_JDPWR_OVERLOAD_LED 1103 -#define CFG_PIN_JDPWR_ENABLE 1104 -#define CFG_PIN_JDPWR_FAULT 1105 - -#endif diff --git a/libs/base/console.ts b/libs/base/console.ts deleted file mode 100644 index c35820c5..00000000 --- a/libs/base/console.ts +++ /dev/null @@ -1,138 +0,0 @@ -/// - -enum ConsolePriority { - Debug = 0, - Log = 1, - Warning = 2, - Error = 3, - Silent = 4 -} - -/** - * Reading and writing data to the console output. - */ -//% weight=12 color=#002050 icon="\uf120" -//% advanced=true -namespace console { - type Listener = (priority: ConsolePriority, text: string) => void; - - /** - * Minimum priority to send messages to listeners - */ - export let minPriority = ConsolePriority.Log; - - //% whenUsed - const listeners: Listener[] = [ - function (priority: ConsolePriority, text: string) { control.__log(priority, text); } - ]; - - export function add(priority: ConsolePriority, message: any) { - if (priority < minPriority) return; - let text = inspect(message); - // add new line - text += "\n"; - // send to listeners - for (let i = 0; i < listeners.length; ++i) - listeners[i](priority, text); - } - - export function debug(text: any) { - add(ConsolePriority.Debug, text); - } - - export function warn(text: any) { - add(ConsolePriority.Warning, text); - } - - export function error(text: any) { - add(ConsolePriority.Error, text); - } - - /** - * Write a line of text to the console output. - * @param value to send - */ - //% weight=90 - //% help=console/log blockGap=8 - //% blockId=console_log block="console log $value" - //% value.shadow=text - export function log(value: any): void { - add(ConsolePriority.Log, value); - } - - /** - * Write a name:value pair as a line of text to the console output. - * @param name name of the value stream, eg: "x" - * @param value to write - */ - //% weight=88 blockGap=8 - //% help=console/log-value - //% blockId=console_log_value block="console|log value %name|= %value" - //% name.shadow=text - //% value.shadow=math_number - export function logValue(name: any, value: any): void { - log(name ? `${inspect(name)}: ${inspect(value)}` : `${inspect(value)}`) - } - - /** - * Convert any object or value to a string representation - * @param obj value to be converted to a string - * @param maxElements [optional] max number values in an object to include in output - */ - export function inspect(obj: any, maxElements = 20): string { - if (typeof obj == "string") { - return obj; - } else if (typeof obj == "number") { - return "" + obj; - } else if (Array.isArray(obj)) { - const asArr = (obj as Array); - if (asArr.length <= maxElements) { - return asArr.join(","); - } else { - return `${asArr.slice(0, maxElements).join(",")}...`; - } - } else { - const asString = obj + ""; - if (asString != "[object Object]" - && asString != "[Object]") { // on arcade at least, default toString is [Object] on hardware instead of standard - return asString; - } - - let keys = Object.keys(obj); - const snipped = keys.length > maxElements; - if (snipped) { - keys = keys.slice(0, maxElements); - } - - return `{${ - keys.reduce( - (prev, currKey) => prev + `\n ${currKey}: ${obj[currKey]}`, - "" - ) + (snipped ? "\n ..." : "") - } -}`; - } - } - - /** - * Adds a listener for the log messages - * @param listener - */ - //% - export function addListener(listener: (priority: ConsolePriority, text: string) => void) { - if (!listener || listeners.indexOf(listener) > -1) return; - listeners.push(listener); - } - - /** - * Removes a listener - * @param listener - */ - //% - export function removeListener(listener: (priority: ConsolePriority, text: string) => void) { - if (!listener) return; - const i = listeners.indexOf(listener); - if (i > -1) - listeners.splice(i, 1); - } -} \ No newline at end of file diff --git a/libs/base/control.cpp b/libs/base/control.cpp deleted file mode 100644 index ba5733bb..00000000 --- a/libs/base/control.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "pxtbase.h" - - -namespace control { - /** - * Gets the number of milliseconds elapsed since power on. - */ - //% help=control/millis weight=50 - //% blockId=control_running_time block="millis (ms)" - int millis() { - return current_time_ms(); - } - - /** - * Gets current time in microseconds. Overflows every ~18 minutes. - */ - //% - int micros() { - return current_time_us() & 0x3fffffff; - } - - /** - * Used internally - */ - //% - void internalOnEvent(int src, int value, Action handler, int flags = 16) { - registerWithDal(src, value, handler, flags); - } - - /** - * Reset the device. - */ - //% weight=30 async help=control/reset blockGap=8 - //% blockId="control_reset" block="reset" - void reset() { - target_reset(); - } - - /** - * Block the current fiber for the given microseconds - * @param micros number of micro-seconds to wait. eg: 4 - */ - //% help=control/wait-micros weight=29 async - //% blockId="control_wait_us" block="wait (µs)%micros" - void waitMicros(int micros) { - sleep_us(micros); - } - - /** - * Run other code in the parallel. - */ - //% help=control/run-in-parallel handlerStatement=1 - //% blockId="control_run_in_parallel" block="run in parallel" blockGap=8 - void runInParallel(Action a) { - pxt::runInParallel(a); - } - - /** - * Blocks the calling thread until the specified event is raised. - */ - //% help=control/wait-for-event async - //% blockId=control_wait_for_event block="wait for event|from %src|with value %value" - void waitForEvent(int src, int value) { - pxt::waitForEvent(src, value); - } - - /** - * Derive a unique, consistent serial number of this device from internal data. - */ - //% blockId="control_device_serial_number" block="device serial number" weight=9 - //% help=control/device-serial-number - int deviceSerialNumber() { - uint64_t serial_num = pxt::getLongSerialNumber(); - return hash_fnv1(&serial_num, sizeof(serial_num)) & 0x3fffffff; - } - - /** - * Derive a unique, consistent 64-bit serial number of this device from internal data. - */ - //% blockId="control_device_long_serial_number" block="device long serial number" weight=9 - //% help=control/device-long-serial-number - Buffer deviceLongSerialNumber() { - uint64_t serial_num = pxt::getLongSerialNumber(); - return mkBuffer((uint8_t*)&serial_num, sizeof(uint64_t)); - } - - /** - * - */ - //% - void __log(int prority, String text) { - if (NULL == text) return; - pxt::sendSerial(text->getUTF8Data(), text->getUTF8Size()); - } - - /** - * Dump internal information about a value. - */ - //% - void dmesgValue(TValue v) { - anyPrint(v); - } -} diff --git a/libs/base/control.ts b/libs/base/control.ts deleted file mode 100644 index a789756d..00000000 --- a/libs/base/control.ts +++ /dev/null @@ -1,185 +0,0 @@ -/** -* Program controls and events. -*/ -//% weight=90 color="#FF5722" icon="\uf110" advanced=true -namespace control { - /** - * Deprecated, use ``control.runInParallel`` instead. - */ - //% deprecated=1 hidden=1 help=control/run-in-background blockAllowMultiple=1 afterOnStart=true - //% blockId="control_run_in_background" block="run in background" blockGap=8 weight=0 - export function runInBackground(a: () => void) { - control.runInParallel(a); - } - - export const enum PXT_PANIC { - CODAL_OOM = 20, - GC_OOM = 21, - GC_TOO_BIG_ALLOCATION = 22, - CODAL_HEAP_ERROR = 30, - CODAL_NULL_DEREFERENCE = 40, - CODAL_USB_ERROR = 50, - CODAL_HARDWARE_CONFIGURATION_ERROR = 90, - - INVALID_BINARY_HEADER = 901, - OUT_OF_BOUNDS = 902, - REF_DELETED = 903, - SIZE = 904, - INVALID_VTABLE = 905, - INTERNAL_ERROR = 906, - NO_SUCH_CONFIG = 907, - NO_SUCH_PIN = 908, - INVALID_ARGUMENT = 909, - MEMORY_LIMIT_EXCEEDED = 910, - SCREEN_ERROR = 911, - MISSING_PROPERTY = 912, - INVALID_IMAGE = 913, - CALLED_FROM_ISR = 914, - HEAP_DUMPED = 915, - STACK_OVERFLOW = 916, - BLOCKING_TO_STRING = 917, - VM_ERROR = 918, - SETTINGS_CLEARED = 920, - SETTINGS_OVERLOAD = 921, - SETTINGS_SECRET_MISSING = 922, - DELETE_ON_CLASS = 923, - - CAST_FIRST = 980, - CAST_FROM_UNDEFINED = 980, - CAST_FROM_BOOLEAN = 981, - CAST_FROM_NUMBER = 982, - CAST_FROM_STRING = 983, - CAST_FROM_OBJECT = 984, - CAST_FROM_FUNCTION = 985, - CAST_FROM_NULL = 989, - - UNHANDLED_EXCEPTION = 999, - } - /** - * Display an error code and stop the program. - * @param code an error number to display. eg: 5 - */ - //% help=control/panic weight=29 - //% blockId="control_panic" block="panic %code" - //% shim=pxtrt::panic - export function panic(code: number) { } - - /** - * Display an error code and stop the program when the assertion is `false`. - */ - //% help=control/assert weight=30 - //% blockId="control_assert" block="assert %cond|with value %code" - export function assert(cond: boolean, code: number) { - if (!cond) { - fail("Assertion failed, code=" + code) - } - } - - export function fail(message: string) { - console.log("Fatal failure: ") - console.log(message) - dmesg(message) - panic(108) - } - - export class AnimationQueue { - running: boolean; - eventID: number; - public interval: number; - - constructor() { - this.running = false; - this.eventID = control.allocateNotifyEvent(); - this.interval = 1; - } - - /** - * Runs 'render' in a loop until it returns false or the 'stop' function is called - */ - runUntilDone(render: () => boolean) { - const evid = this.eventID; - - // if other animation, wait for turn - if (this.running) - control.waitForEvent(DAL.DEVICE_ID_NOTIFY, evid); - - // check if the animation hasn't been cancelled since we've waiting - if (this.isCancelled(evid)) - return; - - // run animation - this.running = true; - while (this.running - && !this.isCancelled(evid) - && render()) { - pause(this.interval); - } - - // check if the animation hasn't been cancelled since we've been waiting - if (this.isCancelled(evid)) - return; - - // we're done - this.running = false; - // unblock 1 fiber - control.raiseEvent(DAL.DEVICE_ID_NOTIFY_ONE, this.eventID); - } - - isCancelled(evid: number) { - return this.eventID !== evid; - } - - /** - * Cancels the current running animation and clears the queue - */ - cancel() { - if (this.running) { - this.running = false; - const evid = this.eventID; - this.eventID = control.allocateNotifyEvent(); - // unblock fibers - control.raiseEvent(DAL.DEVICE_ID_NOTIFY, evid); - } - } - } - - //% shim=pxt::getConfig - export declare function getConfigValue(key: int32, defl: int32): number; - - //% shim=pxt::programHash - export declare function programHash(): number; - - //% shim=pxt::programName - export declare function programName(): string; - - //% shim=control::_ramSize - function _ramSize() { - return 32 * 1024 * 1024; - } - - /** Returns estimated size of memory in bytes. */ - export function ramSize() { - return getConfigValue(DAL.CFG_RAM_BYTES, 0) || _ramSize(); - } - - /** Runs the function and returns run time in microseconds. */ - export function benchmark(f: () => void) { - const t0 = micros() - f() - let t = micros() - t0 - if (t < 0) - t += 0x3fffffff - return t - } -} - -/** - * Convert any value to text - * @param value value to be converted to text - */ -//% help=text/convert-to-text weight=1 -//% block="convert $value=math_number to text" -//% blockId=variable_to_text blockNamespace="text" -function convertToText(value: any): string { - return "" + value; -} diff --git a/libs/base/controlgc.cpp b/libs/base/controlgc.cpp deleted file mode 100644 index b5a621a8..00000000 --- a/libs/base/controlgc.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "pxtbase.h" - - -namespace control { - /** - * Force GC and dump basic information about heap. - */ - //% - void gc() { - pxt::gc(1); - } - - /** - * Force GC and halt waiting for debugger to do a full heap dump. - */ - //% - void heapDump() { - pxt::gc(2); - target_panic(PANIC_HEAP_DUMPED); - } - - - /** - * Set flags used when connecting an external debugger. - */ - //% - void setDebugFlags(int flags) { - debugFlags = flags; - } - - /** - * Record a heap snapshot to debug memory leaks. - */ - //% - void heapSnapshot() { - // only in JS backend for now - } - - /** - * Return true if profiling is enabled in the current build. - */ - //% - bool profilingEnabled() { -#ifdef PXT_PROFILE - return true; -#else - return false; -#endif - } -} diff --git a/libs/base/controlmessage.ts b/libs/base/controlmessage.ts deleted file mode 100644 index d265ea5c..00000000 --- a/libs/base/controlmessage.ts +++ /dev/null @@ -1,41 +0,0 @@ -namespace control.simmessages { - // these events are raised by JS simulator when messages come in - export const CONTROL_MESSAGE_EVT_ID = 2999; - export const CONTROL_MESSAGE_RECEIVED = 1; - - //% shim=pxt::sendMessage - export declare function send(channel: string, message: Buffer, parentOnly?: boolean) : void; - - //% shim=pxt::peekMessageChannel - declare function peekMessageChannel(): string; - - //% shim=pxt::readMessageData - declare function readMessageData(): Buffer; - - let handlers: { [channel: string] : (msg: Buffer) => void} - function consumeMessages() { - while(true) { - // peek channel of next message - const channel = peekMessageChannel(); - if (!channel) break; - // read next message - const msg = readMessageData(); - // send to handler - const handler = handlers && handlers[channel]; - if (handler) - handler(msg); - } - } - - /** - * Registers the handler for a message on a given channel - **/ - export function onReceived(channel: string, handler: (msg: Buffer) => void) { - if (!channel) return; - - if (!handlers) - handlers = {}; - handlers[channel] = handler; - control.onEvent(CONTROL_MESSAGE_EVT_ID, CONTROL_MESSAGE_RECEIVED, consumeMessages); - } -} \ No newline at end of file diff --git a/libs/base/core.cpp b/libs/base/core.cpp deleted file mode 100644 index cd30fe50..00000000 --- a/libs/base/core.cpp +++ /dev/null @@ -1,2029 +0,0 @@ -#include "pxtbase.h" -#include -#include - -using namespace std; - -#define p10(v) __builtin_powi(10, v) - -// try not to create cons-strings shorter than this -#define SHORT_CONCAT_STRING 50 - -namespace pxt { - -PXT_DEF_STRING(emptyString, "") - -static HandlerBinding *handlerBindings; - -HandlerBinding *nextBinding(HandlerBinding *curr, int source, int value) { - for (auto p = curr; p; p = p->next) { - // DEVICE_ID_ANY == DEVICE_EXT_ANY == 0 - if ((p->source == source || p->source == 0) && - (value == -1 || p->value == value || p->value == 0)) { - return p; - } - } - return 0; -} - -HandlerBinding *findBinding(int source, int value) { - return nextBinding(handlerBindings, source, value); -} - -void setBinding(int source, int value, Action act) { - HandlerBinding *curr = NULL; - for (auto p = handlerBindings; p; p = p->next) { - if ((p->source == source) && (p->value == value)) { - curr = p; - break; - } - } - if (curr) { - curr->action = act; - return; - } - curr = new (app_alloc(sizeof(HandlerBinding))) HandlerBinding(); - curr->next = handlerBindings; - curr->source = source; - curr->value = value; - curr->action = act; - registerGC(&curr->action); - handlerBindings = curr; -} - -void coreReset() { - // these are allocated on GC heap, so they will go away together with the reset - handlerBindings = NULL; -} - -struct EmptyBufferLayout { - const void *vtable; - // data needs to be word-aligned, so we use 32 bits for length - int length; - uint8_t data[1]; -}; - -static const EmptyBufferLayout emptyBuffer[1] = {{&pxt::buffer_vt, 0, {0}}}; - -#if PXT_UTF8 -int utf8Len(const char *data, int size) { - int len = 0; - for (int i = 0; i < size; ++i) { - char c = data[i]; - len++; - if ((c & 0x80) == 0x00) { - // skip - } else if ((c & 0xe0) == 0xc0) { - i++; - } else if ((c & 0xf0) == 0xe0) { - i += 2; - } else { - // error; just skip - } - } - return len; -} - -const char *utf8Skip(const char *data, int size, int skip) { - int len = 0; - for (int i = 0; i <= size; ++i) { - char c = data[i]; - len++; - if (len > skip) - return data + i; - if ((c & 0x80) == 0x00) { - // skip - } else if ((c & 0xe0) == 0xc0) { - i++; - } else if ((c & 0xf0) == 0xe0) { - i += 2; - } else { - // error; just skip over - } - } - return NULL; -} - -static char *write3byte(char *dst, uint32_t charCode) { - if (dst) { - *dst++ = 0xe0 | (charCode >> 12); - *dst++ = 0x80 | (0x3f & (charCode >> 6)); - *dst++ = 0x80 | (0x3f & (charCode >> 0)); - } - return dst; -} - -static char *write2byte(char *dst, uint32_t charCode) { - if (dst) { - *dst++ = 0xc0 | (charCode >> 6); - *dst++ = 0x80 | (0x3f & charCode); - } - return dst; -} - -static int utf8canon(char *dst, const char *data, int size) { - int outsz = 0; - for (int i = 0; i < size;) { - uint8_t c = data[i]; - uint32_t charCode = c; - if ((c & 0x80) == 0x00) { - charCode = c; - i++; - } else if ((c & 0xe0) == 0xc0 && i + 1 < size && (data[i + 1] & 0xc0) == 0x80) { - charCode = ((c & 0x1f) << 6) | (data[i + 1] & 0x3f); - if (charCode < 0x80) - goto error; - else - i += 2; - } else if ((c & 0xf0) == 0xe0 && i + 2 < size && (data[i + 1] & 0xc0) == 0x80 && - (data[i + 2] & 0xc0) == 0x80) { - charCode = ((c & 0x0f) << 12) | (data[i + 1] & 0x3f) << 6 | (data[i + 2] & 0x3f); - // don't exclude surrogate pairs, since we're generating them - if (charCode < 0x800 /*|| (0xd800 <= charCode && charCode <= 0xdfff)*/) - goto error; - else - i += 3; - } else if ((c & 0xf8) == 0xf0 && i + 3 < size && (data[i + 1] & 0xc0) == 0x80 && - (data[i + 2] & 0xc0) == 0x80 && (data[i + 3] & 0xc0) == 0x80) { - charCode = ((c & 0x07) << 18) | (data[i + 1] & 0x3f) << 12 | (data[i + 2] & 0x3f) << 6 | - (data[i + 3] & 0x3f); - if (charCode < 0x10000 || charCode > 0x10ffff) - goto error; - else - i += 4; - } else { - goto error; - } - - if (charCode < 0x80) { - outsz += 1; - if (dst) - *dst++ = charCode; - } else if (charCode < 0x800) { - outsz += 2; - dst = write2byte(dst, charCode); - } else if (charCode < 0x10000) { - outsz += 3; - dst = write3byte(dst, charCode); - } else { - outsz += 6; // a surrogate pair - charCode -= 0x10000; - dst = write3byte(dst, 0xd800 + (charCode >> 10)); - dst = write3byte(dst, 0xdc00 + (charCode & 0x3ff)); - } - - continue; - - error: - i++; - outsz += 2; - dst = write2byte(dst, c); - } - return outsz; -} - -static int utf8CharCode(const char *data) { - unsigned char c = *data; - if ((c & 0x80) == 0) { - return c; - } else if ((c & 0xe0) == 0xc0) { - return ((c & 0x1f) << 6) | (data[1] & 0x3f); - } else if ((c & 0xf0) == 0xe0) { - return ((c & 0x0f) << 12) | (data[1] & 0x3f) << 6 | (data[2] & 0x3f); - } else { - return c; // error - } -} - -static bool isUTF8(const char *data, int len) { - for (int i = 0; i < len; ++i) { - if (data[i] & 0x80) - return true; - } - return false; -} - -static void setupSkipList(String r, const char *data, int packed) { - char *dst = (char *)(packed ? PXT_SKIP_DATA_PACK(r) : PXT_SKIP_DATA_IND(r)); - auto len = r->skip.size; - if (data) - memcpy(dst, data, len); - dst[len] = 0; - const char *ptr = dst; - auto skipEntries = PXT_NUM_SKIP_ENTRIES(r); - auto lst = packed ? r->skip_pack.list : r->skip.list; - for (int i = 0; i < skipEntries; ++i) { - ptr = utf8Skip(ptr, (int)(len - (ptr - dst)), PXT_STRING_SKIP_INCR); - if (!ptr) - oops(80); - lst[i] = ptr - dst; - } -} -#endif - -String mkStringCore(const char *data, int len) { - if (len < 0) - len = (int)strlen(data); - if (len == 0) - return (String)emptyString; - - auto vt = &string_inline_ascii_vt; - String r; - -#if PXT_UTF8 - if (data && isUTF8(data, len)) { - vt = len >= PXT_STRING_MIN_SKIP ? &string_skiplist16_packed_vt : &string_inline_utf8_vt; - } - if (vt == &string_skiplist16_packed_vt) { - int ulen = utf8Len(data, len); - r = new (gcAllocate(sizeof(void *) + 2 + 2 + (ulen / PXT_STRING_SKIP_INCR) * 2 + len + 1)) - BoxedString(vt); - r->skip_pack.size = len; - r->skip_pack.length = ulen; - setupSkipList(r, data, 1); - } else -#endif - { - // for ASCII and UTF8 the layout is the same - r = new (gcAllocate(sizeof(void *) + 2 + len + 1)) BoxedString(vt); - r->ascii.length = len; - if (data) - memcpy(r->ascii.data, data, len); - r->ascii.data[len] = 0; - } - - MEMDBG("mkString: len=%d => %p", len, r); - return r; -} - -String mkString(const char *data, int len) { -#if PXT_UTF8 - if (len < 0) - len = (int)strlen(data); - if (len == 0) - return (String)emptyString; - - int sz = utf8canon(NULL, data, len); - if (sz == len) - return mkStringCore(data, len); - // this could be optimized, but it only kicks in when the string isn't valid utf8 - // (or we need to introduce surrogate pairs) which is unlikely to be performance critical - char *tmp = (char *)app_alloc(sz); - utf8canon(tmp, data, len); - auto r = mkStringCore(tmp, sz); - app_free(tmp); - return r; -#else - return mkStringCore(data, len); -#endif -} - -#if PXT_UTF8 -// This converts surrogate pairs, which are encoded as 2 characters of 3 bytes each -// into a proper 4 byte utf-8 character. -uint32_t toRealUTF8(String str, uint8_t *dst) { - auto src = str->getUTF8Data(); - auto len = str->getUTF8Size(); - auto dlen = 0; - - for (unsigned i = 0; i < len; ++i) { - if ((uint8_t)src[i] == 0xED && i + 5 < len) { - auto c0 = utf8CharCode(src + i); - auto c1 = utf8CharCode(src + i + 3); - if (0xd800 <= c0 && c0 < 0xdc00 && 0xdc00 <= c1 && c1 < 0xe000) { - i += 5; - auto charCode = ((c0 - 0xd800) << 10) + (c1 - 0xdc00) + 0x10000; - if (dst) { - dst[dlen] = 0xf0 | (charCode >> 18); - dst[dlen + 1] = 0x80 | (0x3f & (charCode >> 12)); - dst[dlen + 2] = 0x80 | (0x3f & (charCode >> 6)); - dst[dlen + 3] = 0x80 | (0x3f & (charCode >> 0)); - } - dlen += 4; - } - } else { - if (dst) - dst[dlen] = src[i]; - dlen++; - } - } - return dlen; -} -#endif - -Buffer mkBuffer(const void *data, int len) { - if (len <= 0) - return (Buffer)emptyBuffer; - Buffer r = new (gcAllocate(sizeof(BoxedBuffer) + len)) BoxedBuffer(); - r->length = len; - if (data) - memcpy(r->data, data, len); - else - memset(r->data, 0, len); - MEMDBG("mkBuffer: len=%d => %p", len, r); - return r; -} - -static unsigned random_value = 0xC0DA1; - -//% -void seedRandom(unsigned seed) { - random_value = seed; -} - -//% expose -void seedAddRandom(unsigned seed) { - random_value ^= 0xCA2557CB * seed; -} - -unsigned getRandom(unsigned max) { - unsigned m, result; - - do { - m = (unsigned)max; - result = 0; - - do { - // Cycle the LFSR (Linear Feedback Shift Register). - // We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here - // (a true legend in the field!), - // For those interested, it's documented in his paper: - // "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent - // generator for 32-bit Microprocessors" - // https://www.schneier.com/paper-pseudorandom-sequence.html - unsigned r = random_value; - - r = ((((r >> 31) ^ (r >> 6) ^ (r >> 4) ^ (r >> 2) ^ (r >> 1) ^ r) & 1) << 31) | - (r >> 1); - - random_value = r; - - result = ((result << 1) | (r & 0x00000001)); - } while (m >>= 1); - } while (result > (unsigned)max); - - return result; -} - -TNumber BoxedString::charCodeAt(int pos) { -#if PXT_UTF8 - auto ptr = this->getUTF8DataAt(pos); - if (!ptr) - return TAG_NAN; - auto code = utf8CharCode(ptr); - if (!code && ptr == this->getUTF8Data() + this->getUTF8Size()) - return TAG_NAN; - return fromInt(code); -#else - if (0 <= pos && pos < this->ascii.length) { - return fromInt(this->ascii.data[pos]); - } else { - return TAG_NAN; - } -#endif -} - -PXT_DEF_STRING(sTrue, "true") -PXT_DEF_STRING(sFalse, "false") -PXT_DEF_STRING(sUndefined, "undefined") -PXT_DEF_STRING(sNull, "null") -PXT_DEF_STRING(sObject, "[Object]") -PXT_DEF_STRING(sFunction, "[Function]") -PXT_DEF_STRING(sNaN, "NaN") -PXT_DEF_STRING(sInf, "Infinity") -PXT_DEF_STRING(sMInf, "-Infinity") -} // namespace pxt - -#ifndef X86_64 - -namespace String_ { - -//% -String mkEmpty() { - return (String)emptyString; -} - -// TODO support var-args somehow? - -//% -String fromCharCode(int code) { -#if PXT_UTF8 - char buf[3]; - int len; - code &= 0xffff; // JS semantics - if (code < 0x80) { - buf[0] = code; - len = 1; - } else if (code < 0x800) { - buf[0] = 0xc0 | (code >> 6); - buf[1] = 0x80 | ((code >> 0) & 0x3f); - len = 2; - } else { - buf[0] = 0xe0 | (code >> 12); - buf[1] = 0x80 | ((code >> 6) & 0x3f); - buf[2] = 0x80 | ((code >> 0) & 0x3f); - len = 3; - } - return mkStringCore(buf, len); -#else - char buf[] = {(char)code, 0}; - return mkStringCore(buf, 1); -#endif -} - -//% -TNumber charCodeAt(String s, int pos) { - if (!s) - return TAG_NAN; - return s->charCodeAt(pos); -} - -//% -String charAt(String s, int pos) { - auto v = charCodeAt(s, pos); - if (v == TAG_NAN) - return mkEmpty(); - if (!isInt(v)) - oops(81); - return fromCharCode(numValue(v)); -} - -#define IS_CONS(s) ((s)->vtable == &string_cons_vt) -#define IS_EMPTY(s) ((s) == (String)emptyString) - -//% -String concat(String s, String other) { - if (!s) - s = (String)sNull; - if (!other) - other = (String)sNull; - if (IS_EMPTY(s)) - return other; - if (IS_EMPTY(other)) - return s; - - uint32_t lenA, lenB; - -#if PXT_UTF8 - if (IS_CONS(s)) { - // (s->cons.left + s->cons.right) + other = s->cons.left + (s->cons.right + other) - if (IS_CONS(other) || IS_CONS(s->cons.right)) - goto mkCons; - auto lenAR = s->cons.right->getUTF8Size(); - lenB = other->getUTF8Size(); - if (lenAR + lenB > SHORT_CONCAT_STRING) - goto mkCons; - // if (s->cons.right + other) is short enough, use associativity - // to construct a shallower tree; this should keep the live set reasonable - // when someone decides to construct a long string by concatenating - // single characters - - // allocate [r] first, and keep it alive - String r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt); - registerGCObj(r); - r->cons.left = s->cons.left; - // this concat() might trigger GC - r->cons.right = concat(s->cons.right, other); - unregisterGCObj(r); - return r; - } -#endif - - lenA = s->getUTF8Size(); - lenB = other->getUTF8Size(); -#if PXT_UTF8 - if (lenA + lenB > SHORT_CONCAT_STRING) - goto mkCons; -#endif - String r; - { - auto dataA = s->getUTF8Data(); - auto dataB = other->getUTF8Data(); - r = mkStringCore(NULL, lenA + lenB); - auto dst = (char *)r->getUTF8Data(); - memcpy(dst, dataA, lenA); - memcpy(dst + lenA, dataB, lenB); -#if PXT_UTF8 - if (isUTF8(dst, lenA + lenB)) - r->vtable = &string_inline_utf8_vt; -#endif - return r; - } - -#if PXT_UTF8 -mkCons: - r = new (gcAllocate(3 * sizeof(void *))) BoxedString(&string_cons_vt); - r->cons.left = s; - r->cons.right = other; - return r; -#endif -} - -int compare(String a, String b) { - if (a == b) - return 0; - - auto lenA = a->getUTF8Size(); - auto lenB = b->getUTF8Size(); - auto dataA = a->getUTF8Data(); - auto dataB = b->getUTF8Data(); - auto len = lenA < lenB ? lenA : lenB; - - // this also works for UTF8, provided canonical encoding - // which is guaranteed by the constructor - for (unsigned i = 0; i <= len; ++i) { - unsigned char cA = dataA[i]; - unsigned char cB = dataB[i]; - if (cA == cB) - continue; - return cA < cB ? -1 : 1; - } - return 0; -} - -//% -int length(String s) { - return s->getLength(); -} - -#define isspace(c) ((c) == ' ') -#define iswhitespace(c) \ - ((c) == 0x09 || (c) == 0x0B || (c) == 0x0C || (c) == 0x20 || (uint8_t)(c) == 0xA0 || \ - (c) == 0x0A || (c) == 0x0D) - -NUMBER mystrtod(const char *p, char **endp) { - while (iswhitespace(*p)) - p++; - NUMBER m = 1; - NUMBER v = 0; - int dot = 0; - int hasDigit = 0; - if (*p == '+') - p++; - if (*p == '-') { - m = -1; - p++; - } - - while (*p) { - int c = *p - '0'; - if (0 <= c && c <= 9) { - v *= 10; - v += c; - if (dot) - m /= 10; - hasDigit = 1; - } else if (!dot && *p == '.') { - dot = 1; - } else if (!hasDigit) { - return NAN; - } else { - break; - } - p++; - } - - v *= m; - - if (*p == 'e' || *p == 'E') { - p++; - int pw = (int)strtol(p, endp, 10); - v *= p10(pw); - } else { - *endp = (char *)p; - } - - return v; -} - -//% -TNumber toNumber(String s) { - // JSCHECK - char *endptr; - auto data = s->getUTF8Data(); - NUMBER v = mystrtod(data, &endptr); - if (v == 0.0 || v == -0.0) { - // nothing - } else if (!isnormal(v)) - v = NAN; - return fromDouble(v); -} - -//% -String substr(String s, int start, int length) { - if (length <= 0) - return mkEmpty(); - auto slen = (int)s->getLength(); - if (start < 0) - start = max(slen + start, 0); - length = min(length, slen - start); - if (length <= 0) - return mkEmpty(); - auto p = s->getUTF8DataAt(start); -#if PXT_UTF8 - auto ep = s->getUTF8DataAt(start + length); - if (ep == NULL) - oops(82); - return mkStringCore(p, (int)(ep - p)); -#else - return mkStringCore(p, length); -#endif -} - -//% -int indexOf(String s, String searchString, int start) { - if (!s || !searchString) - return -1; - - if (start < 0) - start = 0; - - auto dataA0 = s->getUTF8Data(); - auto dataA = s->getUTF8DataAt(start); - auto offset = dataA - dataA0; - auto lenA = s->getUTF8Size() - offset; - auto lenB = searchString->getUTF8Size(); - - if (dataA == NULL || lenB > lenA) - return -1; - - auto dataB = searchString->getUTF8Data(); - auto firstB = dataB[0]; - while (lenA >= lenB) { - if (*dataA == firstB && !memcmp(dataA, dataB, lenB)) -#if PXT_UTF8 - return utf8Len(dataA0, (int)(dataA - dataA0)); -#else - return dataA - dataA0; -#endif - dataA++; - lenA--; - } - return -1; -} - -//% -int includes(String s, String searchString, int start) { - return -1 != indexOf(s, searchString, start); -} - -} // namespace String_ - -namespace Boolean_ { -//% -bool bang(bool v) { - return v == 0; -} -} // namespace Boolean_ - -namespace pxt { - -// ES5 9.5, 9.6 -unsigned toUInt(TNumber v) { - if (isInt(v)) - return numValue(v); - if (isSpecial(v)) { - if ((intptr_t)v >> 6) - return 1; - else - return 0; - } - if (!v) - return 0; - - NUMBER num = toDouble(v); - if (!isnormal(num)) - return 0; -#ifdef PXT_USE_FLOAT - float rem = fmodf(truncf(num), 4294967296.0); -#else - double rem = fmod(trunc(num), 4294967296.0); -#endif - if (rem < 0.0) - rem += 4294967296.0; - return (unsigned)rem; -} -int toInt(TNumber v) { - return (int)toUInt(v); -} - -NUMBER toDouble(TNumber v) { - if (v == TAG_NAN || v == TAG_UNDEFINED) - return NAN; - if (isTagged(v)) - return toInt(v); - -#ifdef PXT64 - if (isDouble(v)) - return doubleVal(v); -#endif - - ValType t = valType(v); - -#ifndef PXT64 - if (t == ValType::Number) { - BoxedNumber *p = (BoxedNumber *)v; - return p->num; - } -#endif - - if (t == ValType::String) { - // TODO avoid allocation - auto tmp = String_::toNumber((String)v); - auto r = toDouble(tmp); - return r; - } else { - return NAN; - } -} - -float toFloat(TNumber v) { - if (v == TAG_NAN || v == TAG_UNDEFINED) - return NAN; - // optimize for the int case - this will avoid software conversion when FPU is present - if (isTagged(v)) - return toInt(v); - return (float)toDouble(v); -} - -#if !defined(PXT_HARD_FLOAT) && !defined(PXT_USE_FLOAT) -union NumberConv { - double v; - struct { - uint32_t word0; - uint32_t word1; - }; -}; - -static inline TValue doubleToInt(double x) { - NumberConv cnv; - cnv.v = x; - - if (cnv.word1 == 0 && cnv.word0 == 0) - return TAG_NUMBER(0); - - auto ex = (int)((cnv.word1 << 1) >> 21) - 1023; - - // DMESG("v=%d/1000 %p %p %d", (int)(x * 1000), cnv.word0, cnv.word1, ex); - - if (ex < 0 || ex > 29) { - // the 'MININT' case - if (ex == 30 && cnv.word0 == 0 && cnv.word1 == 0xC1D00000) - return (TValue)(0x80000001); - return NULL; - } - - int32_t r; - - if (ex <= 20) { - if (cnv.word0) - return TAG_UNDEFINED; - if (cnv.word1 << (ex + 12)) - return TAG_UNDEFINED; - r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11); - } else { - if (cnv.word0 << (ex - 20)) - return TAG_UNDEFINED; - r = ((cnv.word1 << 11) | 0x80000000) >> (20 - ex + 11); - r |= cnv.word0 >> (32 - (ex - 20)); - } - - if (cnv.word1 >> 31) - return TAG_NUMBER(-r); - else - return TAG_NUMBER(r); -} -#else -static inline TValue doubleToInt(NUMBER r) { -#ifdef PXT64 - if ((int)r == r) - return TAG_NUMBER((int)r); -#else - int ri = ((int)r) << 1; - if ((ri >> 1) == r) - return (TNumber)(uintptr_t)(ri | 1); -#endif - return TAG_UNDEFINED; -} -#endif - -TNumber fromDouble(NUMBER r) { -#ifndef PXT_BOX_DEBUG - auto i = doubleToInt(r); - if (i) - return i; -#endif - if (isnan(r)) - return TAG_NAN; -#ifdef PXT64 - return tvalueFromDouble(r); -#else - BoxedNumber *p = NEW_GC(BoxedNumber); - p->num = r; - MEMDBG("mkNum: %d/1000 => %p", (int)(r * 1000), p); - return (TNumber)p; -#endif -} - -TNumber fromFloat(float r) { - // TODO optimize - return fromDouble(r); -} - -TNumber fromInt(int v) { - if (canBeTagged(v)) - return TAG_NUMBER(v); - return fromDouble(v); -} - -TNumber fromUInt(unsigned v) { -#ifndef PXT_BOX_DEBUG - if (v <= 0x3fffffff) - return TAG_NUMBER(v); -#endif - return fromDouble(v); -} - -TValue fromBool(bool v) { - if (v) - return TAG_TRUE; - else - return TAG_FALSE; -} - -TNumber eqFixup(TNumber v) { - if (v == TAG_NULL) - return TAG_UNDEFINED; - if (v == TAG_TRUE) - return TAG_NUMBER(1); - if (v == TAG_FALSE) - return TAG_NUMBER(0); - return v; -} - -static inline bool eq_core(TValue a, TValue b, ValType ta) { -#ifndef PXT_BOX_DEBUG - auto aa = (intptr_t)a; - auto bb = (intptr_t)b; - - // if at least one of the values is tagged, they are not equal - if ((aa | bb) & 3) - return false; -#endif - - if (ta == ValType::String) - return String_::compare((String)a, (String)b) == 0; - else if (ta == ValType::Number) - return toDouble(a) == toDouble(b); - else - return a == b; -} - -bool eqq_bool(TValue a, TValue b) { - if (a == TAG_NAN || b == TAG_NAN) - return false; - - if (a == b) - return true; - - if (bothNumbers(a, b)) - return false; - - ValType ta = valType(a); - ValType tb = valType(b); - - if (ta != tb) - return false; - - return eq_core(a, b, ta); -} - -bool eq_bool(TValue a, TValue b) { - if (a == TAG_NAN || b == TAG_NAN) - return false; - - if (eqFixup(a) == eqFixup(b)) - return true; - - if (bothNumbers(a, b)) - return false; - - ValType ta = valType(a); - ValType tb = valType(b); - - if ((ta == ValType::String && tb == ValType::Number) || - (tb == ValType::String && ta == ValType::Number)) - return toDouble(a) == toDouble(b); - - if (ta == ValType::Boolean) { - a = eqFixup(a); - ta = ValType::Number; - } - if (tb == ValType::Boolean) { - b = eqFixup(b); - tb = ValType::Number; - } - - if (ta != tb) - return false; - - return eq_core(a, b, ta); -} - -// TODO move to assembly -//% -bool switch_eq(TValue a, TValue b) { - if (eq_bool(a, b)) { - return true; - } - return false; -} - -} // namespace pxt - -#define NUMOP(op) return fromDouble(toDouble(a) op toDouble(b)); -#define BITOP(op) return fromInt(toInt(a) op toInt(b)); -namespace numops { - -int toBool(TValue v) { - if (isTagged(v)) { - if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NAN || v == TAG_NULL || - v == TAG_NUMBER(0)) - return 0; - else - return 1; - } - - ValType t = valType(v); - if (t == ValType::String) { - String s = (String)v; - if (IS_EMPTY(s)) - return 0; - } else if (t == ValType::Number) { - auto x = toDouble(v); - if (isnan(x) || x == 0.0 || x == -0.0) - return 0; - else - return 1; - } - - return 1; -} - -int toBoolDecr(TValue v) { - if (v == TAG_TRUE) - return 1; - if (v == TAG_FALSE) - return 0; - return toBool(v); -} - -// The integer, non-overflow case for add/sub/bit opts is handled in assembly - -#ifdef PXT_VM -#define NUMOP2(op) \ - if (bothNumbers(a, b)) { \ - auto tmp = (int64_t)numValue(a) op(int64_t) numValue(b); \ - if ((int)tmp == tmp) \ - return TAG_NUMBER((int)tmp); \ - } \ - NUMOP(op) -#else -#define NUMOP2(op) NUMOP(op) -#endif - -//% -TNumber adds(TNumber a, TNumber b){NUMOP2(+)} - -//% -TNumber subs(TNumber a, TNumber b){NUMOP2(-)} - -//% -TNumber muls(TNumber a, TNumber b) { - if (bothNumbers(a, b)) { -#ifdef PXT64 - auto tmp = (int64_t)numValue(a) * (int64_t)numValue(b); - if ((int)tmp == tmp) - return TAG_NUMBER((int)tmp); -#else - int aa = (int)a; - int bb = (int)b; - // if both operands fit 15 bits, the result will not overflow int - if ((aa >> 15 == 0 || aa >> 15 == -1) && (bb >> 15 == 0 || bb >> 15 == -1)) { - // it may overflow 31 bit int though - use fromInt to convert properly - return fromInt((aa >> 1) * (bb >> 1)); - } -#endif - } - NUMOP(*) -} - -//% -TNumber div(TNumber a, TNumber b) { - if (b == TAG_NUMBER(1)) - return a; - NUMOP(/) -} - -//% -TNumber mod(TNumber a, TNumber b) { - if (isInt(a) && isInt(b) && numValue(b)) - BITOP(%) - return fromDouble(fmod(toDouble(a), toDouble(b))); -} - -//% -TNumber lsls(TNumber a, TNumber b) { - return fromInt(toInt(a) << (toInt(b) & 0x1f)); -} - -//% -TNumber lsrs(TNumber a, TNumber b) { - return fromUInt(toUInt(a) >> (toUInt(b) & 0x1f)); -} - -//% -TNumber asrs(TNumber a, TNumber b) { - return fromInt(toInt(a) >> (toInt(b) & 0x1f)); -} - -//% -TNumber eors(TNumber a, TNumber b){BITOP(^)} - -//% -TNumber orrs(TNumber a, TNumber b){BITOP(|)} - -//% -TNumber bnot(TNumber a) { - return fromInt(~toInt(a)); -} - -//% -TNumber ands(TNumber a, TNumber b) { - BITOP(&) -} - -#ifdef PXT64 -#define CMPOP_RAW(op, t, f) \ - if (bothNumbers(a, b)) \ - return numValue(a) op numValue(b) ? t : f; \ - int cmp = valCompare(a, b); \ - return cmp != -2 && cmp op 0 ? t : f; -#else -#define CMPOP_RAW(op, t, f) \ - if (bothNumbers(a, b)) \ - return (intptr_t)a op((intptr_t)b) ? t : f; \ - int cmp = valCompare(a, b); \ - return cmp != -2 && cmp op 0 ? t : f; -#endif - -#define CMPOP(op) CMPOP_RAW(op, TAG_TRUE, TAG_FALSE) - -// 7.2.13 Abstract Relational Comparison -static int valCompare(TValue a, TValue b) { - if (a == TAG_NAN || b == TAG_NAN) - return -2; - - ValType ta = valType(a); - ValType tb = valType(b); - - if (ta == ValType::String && tb == ValType::String) - return String_::compare((String)a, (String)b); - - if (a == b) - return 0; - - auto da = toDouble(a); - auto db = toDouble(b); - - if (isnan(da) || isnan(db)) - return -2; - - if (da < db) - return -1; - else if (da > db) - return 1; - else - return 0; -} - -//% -bool lt_bool(TNumber a, TNumber b){CMPOP_RAW(<, true, false)} - -//% -TNumber le(TNumber a, TNumber b){CMPOP(<=)} - -//% -TNumber lt(TNumber a, TNumber b){CMPOP(<)} - -//% -TNumber ge(TNumber a, TNumber b){CMPOP(>=)} - -//% -TNumber gt(TNumber a, TNumber b){CMPOP(>)} - -//% -TNumber eq(TNumber a, TNumber b) { - return pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber neq(TNumber a, TNumber b) { - return !pxt::eq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber eqq(TNumber a, TNumber b) { - return pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -//% -TNumber neqq(TNumber a, TNumber b) { - return !pxt::eqq_bool(a, b) ? TAG_TRUE : TAG_FALSE; -} - -// How many significant digits mycvt() should output. -// This cannot be more than 15, as this is the most that can be accurately represented -// in 64 bit double. Otherwise this code may crash. -#define DIGITS 15 - -static const uint64_t pows[] = { - 1LL, 10LL, 100LL, 1000LL, 10000LL, - 100000LL, 1000000LL, 10000000LL, 100000000LL, 1000000000LL, - 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL, -}; - -// The basic idea is we convert d to a 64 bit integer with DIGITS -// digits, and then print it out, putting dot in the right place. - -void mycvt(NUMBER d, char *buf) { - if (d < 0) { - *buf++ = '-'; - d = -d; - } - - if (!d) { - *buf++ = '0'; - *buf++ = 0; - return; - } - - int pw = (int)log10(d); - int e = 1; - - // if outside 1e-6 -- 1e21 range, we use the e-notation - if (d < 1e-6 || d > 1e21) { - // normalize number to 1.XYZ, save e, and reset pw - if (pw < 0) - d *= p10(-pw); - else - d /= p10(pw); - e = pw; - pw = 0; - } - - int trailingZ = 0; - int dotAfter = pw + 1; // at which position the dot should be in the number - - uint64_t dd; - - // normalize number to be integer with exactly DIGITS digits - if (pw >= DIGITS) { - // if the number is larger than DIGITS, we need trailing zeroes - trailingZ = pw - DIGITS + 1; - dd = (uint64_t)(d / p10(trailingZ) + 0.5); - } else { - dd = (uint64_t)(d * p10(DIGITS - pw - 1) + 0.5); - } - - // if number is less than 1, we need 0.00...00 at the beginning - if (dotAfter < 1) { - *buf++ = '0'; - *buf++ = '.'; - int n = -dotAfter; - while (n--) - *buf++ = '0'; - } - - // now print out the actual number - for (int i = DIGITS - 1; i >= 0; i--) { - uint64_t q = pows[i]; - // this may be faster than fp-division and fmod(); or maybe not - // anyways, it works - int k = '0'; - while (dd >= q) { - dd -= q; - k++; - } - *buf++ = k; - // if we're after dot, and what's left is zeroes, stop - if (dd == 0 && (DIGITS - i) >= dotAfter) - break; - // print the dot, if we arrived at it - if ((DIGITS - i) == dotAfter) - *buf++ = '.'; - } - - // print out remaining trailing zeroes if any - while (trailingZ-- > 0) - *buf++ = '0'; - - // if we used e-notation, handle that - if (e != 1) { - *buf++ = 'e'; - if (e > 0) - *buf++ = '+'; - itoa(e, buf); - } else { - *buf = 0; - } -} - -#if 0 -//% -TValue floatAsInt(TValue x) { - return doubleToInt(toDouble(x)); -} - -//% shim=numops::floatAsInt -function floatAsInt(v: number): number { return 0 } - -function testInt(i: number) { - if (floatAsInt(i) != i) - control.panic(101) - if (floatAsInt(i + 0.5) != null) - control.panic(102) - if (floatAsInt(i + 0.00001) != null) - control.panic(103) -} - -function testFloat(i: number) { - if (floatAsInt(i) != null) - control.panic(104) -} - -function testFloatAsInt() { - for (let i = 0; i < 0xffff; ++i) { - testInt(i) - testInt(-i) - testInt(i * 10000) - testInt(i << 12) - testInt(i + 0x3fff0001) - testInt(-i - 0x3fff0002) - testFloat(i + 0x3fffffff + 1) - testFloat((i + 10000) * 1000000) - } -} -#endif - -String toString(TValue v) { - ValType t = valType(v); - - if (t == ValType::String) { - return (String)v; - } else if (t == ValType::Number) { - char buf[64]; - - if (isInt(v)) { - itoa(numValue(v), buf); - return mkStringCore(buf); - } - - if (v == TAG_NAN) - return (String)(void *)sNaN; - - auto x = toDouble(v); - -#ifdef PXT_BOX_DEBUG - if (x == (int)x) { - itoa((int)x, buf); - return mkStringCore(buf); - } -#endif - - if (isinf(x)) { - if (x < 0) - return (String)(void *)sMInf; - else - return (String)(void *)sInf; - } else if (isnan(x)) { - return (String)(void *)sNaN; - } - mycvt(x, buf); - - return mkStringCore(buf); - } else if (t == ValType::Function) { - return (String)(void *)sFunction; - } else { - if (v == TAG_UNDEFINED) - return (String)(void *)sUndefined; - else if (v == TAG_FALSE) - return (String)(void *)sFalse; - else if (v == TAG_NAN) - return (String)(void *)sNaN; - else if (v == TAG_TRUE) - return (String)(void *)sTrue; - else if (v == TAG_NULL) - return (String)(void *)sNull; - return (String)(void *)sObject; - } -} - -} // namespace numops - -namespace Math_ { -//% -TNumber pow(TNumber x, TNumber y) { -#ifdef PXT_POWI - // regular pow() from math.h is 4k of code - return fromDouble(__builtin_powi(toDouble(x), toInt(y))); -#else - return fromDouble(::pow(toDouble(x), toDouble(y))); -#endif -} - -NUMBER randomDouble() { - return getRandom(UINT_MAX) / ((NUMBER)UINT_MAX + 1) + - getRandom(0xffffff) / ((NUMBER)UINT_MAX * 0xffffff); -} - -//% -TNumber random() { - return fromDouble(randomDouble()); -} - -//% -TNumber randomRange(TNumber min, TNumber max) { - if (isInt(min) && isInt(max)) { - int mini = numValue(min); - int maxi = numValue(max); - if (mini > maxi) { - int temp = mini; - mini = maxi; - maxi = temp; - } - if (maxi == mini) - return fromInt(mini); - else - return fromInt(mini + getRandom(maxi - mini)); - } else { - auto mind = toDouble(min); - auto maxd = toDouble(max); - if (mind > maxd) { - auto temp = mind; - mind = maxd; - maxd = temp; - } - if (maxd == mind) - return fromDouble(mind); - else { - return fromDouble(mind + randomDouble() * (maxd - mind)); - } - } -} - -#define SINGLE(op) return fromDouble(::op(toDouble(x))); - -//% -TNumber log(TNumber x){SINGLE(log)} - -//% -TNumber log10(TNumber x){SINGLE(log10)} - -//% -TNumber floor(TNumber x){SINGLE(floor)} - -//% -TNumber ceil(TNumber x){SINGLE(ceil)} - -//% -TNumber trunc(TNumber x){SINGLE(trunc)} - -//% -TNumber round(TNumber x) { - // In C++, round(-1.5) == -2, while in JS, round(-1.5) == -1. Align to the JS convention for - // consistency between simulator and device. The following does rounding with ties (x.5) going - // towards positive infinity. - return fromDouble(::floor(toDouble(x) + 0.5)); -} - -//% -int imul(int x, int y) { - return x * y; -} - -//% -int idiv(int x, int y) { - return x / y; -} -} // namespace Math_ - -namespace Array_ { -RefCollection *mk() { - auto r = NEW_GC(RefCollection); - MEMDBG("mkColl: => %p", r); - return r; -} -int length(RefCollection *c) { - return c->length(); -} -void setLength(RefCollection *c, int newLength) { - c->setLength(newLength); -} -void push(RefCollection *c, TValue x) { - c->head.push(x); -} -TValue pop(RefCollection *c) { - return c->head.pop(); -} -TValue getAt(RefCollection *c, int x) { - return c->head.get(x); -} -void setAt(RefCollection *c, int x, TValue y) { - c->head.set(x, y); -} -TValue removeAt(RefCollection *c, int x) { - return c->head.remove(x); -} -void insertAt(RefCollection *c, int x, TValue value) { - c->head.insert(x, value); -} -int indexOf(RefCollection *c, TValue x, int start) { - auto data = c->head.getData(); - auto len = c->head.getLength(); - for (unsigned i = 0; i < len; i++) { - if (pxt::eq_bool(data[i], x)) { - return (int)i; - } - } - return -1; -} -bool removeElement(RefCollection *c, TValue x) { - int idx = indexOf(c, x, 0); - if (idx >= 0) { - decr(removeAt(c, idx)); - return 1; - } - return 0; -} -} // namespace Array_ - -namespace pxt { -int debugFlags; - -//% -void *ptrOfLiteral(int offset); - -#ifdef PXT_VM -unsigned programSize() { - return 0; -} -#else -//% -unsigned programSize() { - return bytecode[17] * 8; -} -#endif - -void deepSleep() __attribute__((weak)); -//% -void deepSleep() {} - -int *getBootloaderConfigData() __attribute__((weak)); -int *getBootloaderConfigData() { - return NULL; -} - -//% -int getConfig(int key, int defl) { -#ifdef PXT_VM - int *cfgData = vmImg->configData; -#else - int *cfgData = bytecode ? *(int **)&bytecode[18] : NULL; -#endif - - if (cfgData) { - for (int i = 0;; i += 2) { - if (cfgData[i] == key) - return cfgData[i + 1]; - if (cfgData[i] == 0) - break; - } - } - - cfgData = getBootloaderConfigData(); - - if (cfgData) { - for (int i = 0;; i += 2) { - if (cfgData[i] == key) - return cfgData[i + 1]; - if (cfgData[i] == 0) - break; - } - } - - return defl; -} - -} // namespace pxt - -namespace pxtrt { -//% -TValue ldlocRef(RefRefLocal *r) { - return r->v; -} - -//% -void stlocRef(RefRefLocal *r, TValue v) { - r->v = v; -} - -//% -RefRefLocal *mklocRef() { - auto r = NEW_GC(RefRefLocal); - MEMDBG("mklocRef: => %p", r); - return r; -} - -// Store a captured local in a closure. It returns the action, so it can be chained. -//% -RefAction *stclo(RefAction *a, int idx, TValue v) { - // DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v); - a->stCore(idx, v); - return a; -} - -//% -void panic(int code) { - soft_panic(code); -} - -//% -String emptyToNull(String s) { - if (!s || IS_EMPTY(s)) - return NULL; - return s; -} - -//% -int ptrToBool(TValue p) { - if (p) { - decr(p); - return 1; - } else { - return 0; - } -} - -RefMap *mkMap() { - auto r = NEW_GC(RefMap); - MEMDBG("mkMap: => %p", r); - return r; -} - -TValue mapGetByString(RefMap *map, String key) { - int i = map->findIdx(key); - if (i < 0) { - return 0; - } - return map->values.get(i); -} - -#ifdef PXT_VM -#define IFACE_MEMBER_NAMES vmImg->ifaceMemberNames -#else -#define IFACE_MEMBER_NAMES *(uintptr_t **)&bytecode[22] -#endif - -int lookupMapKey(String key) { - auto arr = IFACE_MEMBER_NAMES; - auto len = *arr++; - int l = 1U; // skip index 0 - it's invalid - int r = (int)len - 1; - auto ikey = (uintptr_t)key; - if (arr[l] <= ikey && ikey <= arr[r]) { - while (l <= r) { - auto m = (l + r) >> 1; - if (arr[m] == ikey) - return m; - else if (arr[m] < ikey) - l = m + 1; - else - r = m - 1; - } - } else { - while (l <= r) { - int m = (l + r) >> 1; - auto cmp = String_::compare((String)arr[m], key); - if (cmp == 0) - return m; - else if (cmp < 0) - l = m + 1; - else - r = m - 1; - } - } - return 0; -} - -TValue mapGet(RefMap *map, unsigned key) { - auto arr = (String *)IFACE_MEMBER_NAMES; - auto r = mapGetByString(map, arr[key + 1]); - map->unref(); - return r; -} - -void mapSetByString(RefMap *map, String key, TValue val) { - int i = map->findIdx(key); - if (i < 0) { - map->keys.push((TValue)key); - map->values.push(val); - } else { - map->values.set(i, val); - } -} - -void mapSet(RefMap *map, unsigned key, TValue val) { - auto arr = (String *)IFACE_MEMBER_NAMES; - mapSetByString(map, arr[key + 1], val); - decr(val); - map->unref(); -} - -// -// Debugger -// - -// This is only to be called once at the beginning of lambda function -//% -void *getGlobalsPtr() { -#ifdef DEVICE_GROUP_ID_USER - fiber_set_group(DEVICE_GROUP_ID_USER); -#endif - - return globals; -} - -//% -void runtimeWarning(String s) { - // noop for now -} -} // namespace pxtrt -#endif - -namespace pxt { - -//% -ValType valType(TValue v) { - if (isTagged(v)) { - if (!v) - return ValType::Undefined; - - if (isInt(v) || v == TAG_NAN) - return ValType::Number; - if (v == TAG_TRUE || v == TAG_FALSE) - return ValType::Boolean; - else if (v == TAG_NULL) - return ValType::Object; - else { - oops(1); - return ValType::Object; - } -#ifdef PXT64 - } else if (isDouble(v)) { - return ValType::Number; -#endif - } else { - auto vt = getVTable((RefObject *)v); - if (vt->magic == VTABLE_MAGIC) - return vt->objectType; - else - return ValType::Object; - } -} - -PXT_DEF_STRING(sObjectTp, "object") -PXT_DEF_STRING(sBooleanTp, "boolean") -PXT_DEF_STRING(sStringTp, "string") -PXT_DEF_STRING(sNumberTp, "number") -PXT_DEF_STRING(sFunctionTp, "function") -PXT_DEF_STRING(sUndefinedTp, "undefined") - -//% expose -String typeOf(TValue v) { - switch (valType(v)) { - case ValType::Undefined: - return (String)sUndefinedTp; - case ValType::Boolean: - return (String)sBooleanTp; - case ValType::Number: - return (String)sNumberTp; - case ValType::String: - return (String)sStringTp; - case ValType::Object: - return (String)sObjectTp; - case ValType::Function: - return (String)sFunctionTp; - default: - oops(2); - return 0; - } -} - -// Maybe in future we will want separate print methods; for now ignore -void anyPrint(TValue v) { - if (valType(v) == ValType::Object) { - if (isRefCounted(v)) { - auto o = (RefObject *)v; - auto vt = getVTable(o); - auto meth = ((RefObjectMethod)vt->methods[1]); - if ((void *)meth == (void *)&anyPrint) - DMESG("[RefObject vt=%p cl=%d sz=%d]", o->vtable, vt->classNo, vt->numbytes); - else - meth(o); - } else { - DMESG("[Native %p]", v); - } - } else { -#ifndef X86_64 - String s = numops::toString(v); - DMESG("[%s %p = %s]", pxt::typeOf(v)->getUTF8Data(), v, s->getUTF8Data()); - decr((TValue)s); -#endif - } -} - -static void dtorDoNothing() {} - -#define PRIM_VTABLE(name, objectTp, tp, szexpr) \ - static uint32_t name##_size(tp *p) { return TOWORDS(sizeof(tp) + szexpr); } \ - DEF_VTABLE(name##_vt, tp, objectTp, (void *)&dtorDoNothing, (void *)&anyPrint, 0, \ - (void *)&name##_size) - -#define NOOP ((void)0) - -#define STRING_VT(name, fix, scan, gcsize, data, utfsize, length, dataAt) \ - static uint32_t name##_gcsize(BoxedString *p) { return TOWORDS(sizeof(void *) + (gcsize)); } \ - static void name##_gcscan(BoxedString *p) { scan; } \ - static const char *name##_data(BoxedString *p) { \ - fix; \ - return data; \ - } \ - static uint32_t name##_utfsize(BoxedString *p) { \ - fix; \ - return utfsize; \ - } \ - static uint32_t name##_length(BoxedString *p) { \ - fix; \ - return length; \ - } \ - static const char *name##_dataAt(BoxedString *p, uint32_t idx) { \ - fix; \ - return dataAt; \ - } \ - DEF_VTABLE(name##_vt, BoxedString, ValType::String, (void *)&dtorDoNothing, (void *)&anyPrint, \ - (void *)&name##_gcscan, (void *)&name##_gcsize, (void *)&name##_data, \ - (void *)&name##_utfsize, (void *)&name##_length, (void *)&name##_dataAt) - -void gcMarkArray(void *data); -void gcScan(TValue v); - -#if PXT_UTF8 -static const char *skipLookup(BoxedString *p, uint32_t idx, int packed) { - if (idx > p->skip.length) - return NULL; - auto ent = idx / PXT_STRING_SKIP_INCR; - auto data = packed ? PXT_SKIP_DATA_PACK(p) : PXT_SKIP_DATA_IND(p); - auto size = p->skip.size; - if (ent) { - auto off = packed ? p->skip_pack.list[ent - 1] : p->skip.list[ent - 1]; - data += off; - size -= off; - idx &= PXT_STRING_SKIP_INCR - 1; - } - return utf8Skip(data, size, idx); -} - -extern LLSegment workQueue; - -static uint32_t fixSize(BoxedString *p, uint32_t *len) { - uint32_t tlen = 0; - uint32_t sz = 0; - if (workQueue.getLength()) - oops(81); - workQueue.push((TValue)p); - while (workQueue.getLength()) { - p = (BoxedString *)workQueue.pop(); - if (IS_CONS(p)) { - workQueue.push((TValue)p->cons.right); - workQueue.push((TValue)p->cons.left); - } else { - tlen += p->getLength(); - sz += p->getUTF8Size(); - } - } - *len = tlen; - return sz; -} - -static void fixCopy(BoxedString *p, char *dst) { - if (workQueue.getLength()) - oops(81); - - workQueue.push((TValue)p); - while (workQueue.getLength()) { - p = (BoxedString *)workQueue.pop(); - if (IS_CONS(p)) { - workQueue.push((TValue)p->cons.right); - workQueue.push((TValue)p->cons.left); - } else { - auto sz = p->getUTF8Size(); - memcpy(dst, p->getUTF8Data(), sz); - dst += sz; - } - } -} - -// switches CONS representation into skip list representation -// does not switch representation of CONS' children -static void fixCons(BoxedString *r) { - uint32_t length = 0; - auto sz = fixSize(r, &length); - auto numSkips = length / PXT_STRING_SKIP_INCR; - // allocate first, while [r] still holds references to its children - // because allocation might trigger GC - auto data = (uint16_t *)gcAllocateArray(numSkips * 2 + sz + 1); - // copy, while [r] is still cons - fixCopy(r, (char *)(data + numSkips)); - // now, set [r] up properly - r->vtable = &string_skiplist16_vt; - r->skip.size = sz; - r->skip.length = length; - r->skip.list = data; - setupSkipList(r, NULL, 0); -} -#endif - -STRING_VT(string_inline_ascii, NOOP, NOOP, 2 + p->ascii.length + 1, p->ascii.data, p->ascii.length, - p->ascii.length, idx <= p->ascii.length ? p->ascii.data + idx : NULL) -#if PXT_UTF8 -STRING_VT(string_inline_utf8, NOOP, NOOP, 2 + p->utf8.size + 1, p->utf8.data, p->utf8.size, - utf8Len(p->utf8.data, p->utf8.size), utf8Skip(p->utf8.data, p->utf8.size, idx)) -STRING_VT(string_skiplist16, NOOP, if (p->skip.list) gcMarkArray(p->skip.list), 2 * sizeof(void *), - PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length, skipLookup(p, idx, 0)) -STRING_VT(string_skiplist16_packed, NOOP, NOOP, 2 + 2 + PXT_NUM_SKIP_ENTRIES(p) * 2 + p->skip.size + 1, - PXT_SKIP_DATA_PACK(p), p->skip.size, p->skip.length, skipLookup(p, idx, 1)) -STRING_VT(string_cons, fixCons(p), (gcScan((TValue)p->cons.left), gcScan((TValue)p->cons.right)), - 2 * sizeof(void *), PXT_SKIP_DATA_IND(p), p->skip.size, p->skip.length, - skipLookup(p, idx, 0)) -#endif - -PRIM_VTABLE(number, ValType::Number, BoxedNumber, 0) -PRIM_VTABLE(buffer, ValType::Object, BoxedBuffer, p->length) -// PRIM_VTABLE(action, ValType::Function, RefAction, ) - -void failedCast(TValue v, void *addr) { - DMESG("failed type check for %p @%p", v, addr); - auto vt = getAnyVTable(v); - if (vt) { - DMESG("VT %p - objtype %d classNo %d", vt, vt->objectType, vt->classNo); - } - - int code; - if (v == TAG_NULL) - code = PANIC_CAST_FROM_NULL; - else - code = PANIC_CAST_FIRST + (int)valType(v); - soft_panic(code); -} - -void missingProperty(TValue v) { - DMESG("missing property on %p", v); - soft_panic(PANIC_MISSING_PROPERTY); -} - -#ifdef PXT_PROFILE -struct PerfCounter *perfCounters; - -struct PerfCounterInfo { - uint32_t numPerfCounters; - char *perfCounterNames[0]; -}; - -#define PERF_INFO ((PerfCounterInfo *)(((uintptr_t *)bytecode)[13])) - -void initPerfCounters() { - auto n = PERF_INFO->numPerfCounters; - perfCounters = new PerfCounter[n]; - memset(perfCounters, 0, n * sizeof(PerfCounter)); -} - -void dumpPerfCounters() { - auto info = PERF_INFO; - DMESG("calls,us,name"); - for (uint32_t i = 0; i < info->numPerfCounters; ++i) { - auto c = &perfCounters[i]; - DMESG("%d,%d,%s", c->numstops, c->value, info->perfCounterNames[i]); - } -} - -void startPerfCounter(PerfCounters n) { - if (!perfCounters) - return; - auto c = &perfCounters[(uint32_t)n]; - if (c->start) - oops(50); - c->start = PERF_NOW(); -} - -void stopPerfCounter(PerfCounters n) { - if (!perfCounters) - return; - auto c = &perfCounters[(uint32_t)n]; - if (!c->start) - oops(51); - c->value += PERF_NOW() - c->start; - c->start = 0; - c->numstops++; -} -#endif - -// Exceptions - -#ifndef PXT_EXN_CTX -#define PXT_EXN_CTX() getThreadContext() -#endif - -typedef void (*RestoreStateType)(TryFrame *, ThreadContext *); -#ifndef pxt_restore_exception_state -#define pxt_restore_exception_state ((RestoreStateType)(((uintptr_t *)bytecode)[14])) -#endif - -//% -TryFrame *beginTry() { - auto ctx = PXT_EXN_CTX(); - auto frame = (TryFrame *)app_alloc(sizeof(TryFrame)); - frame->parent = ctx->tryFrame; - ctx->tryFrame = frame; - return frame; -} - -//% expose -void endTry() { - auto ctx = PXT_EXN_CTX(); - auto f = ctx->tryFrame; - if (!f) - oops(51); - ctx->tryFrame = f->parent; - app_free(f); -} - -//% expose -void throwValue(TValue v) { - auto ctx = PXT_EXN_CTX(); - auto f = ctx->tryFrame; - if (!f) { - DMESG("unhandled exception, value:"); - anyPrint(v); - target_panic(PANIC_UNHANDLED_EXCEPTION); - } - ctx->tryFrame = f->parent; - TryFrame copy = *f; - app_free(f); - ctx->thrownValue = v; - pxt_restore_exception_state(©, ctx); -} - -//% expose -TValue getThrownValue() { - auto ctx = PXT_EXN_CTX(); - auto v = ctx->thrownValue; - ctx->thrownValue = TAG_NON_VALUE; - if (v == TAG_NON_VALUE) - oops(51); - return v; -} - -//% expose -void endFinally() { - auto ctx = PXT_EXN_CTX(); - if (ctx->thrownValue == TAG_NON_VALUE) - return; - throwValue(getThrownValue()); -} - -// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function -uint32_t hash_fnv1(const void *data, unsigned len) { - const uint8_t *d = (const uint8_t *)data; - uint32_t h = 0x811c9dc5; - while (len--) - h = (h * 0x1000193) ^ *d++; - return h; -} - -// redefined in melody.cpp -__attribute__((weak)) int redirectSamples(int16_t *dst, int numsamples, int samplerate) { - return 0; -} - -} // namespace pxt diff --git a/libs/base/docs/blocks/pause-until.md b/libs/base/docs/blocks/pause-until.md deleted file mode 100644 index 24172331..00000000 --- a/libs/base/docs/blocks/pause-until.md +++ /dev/null @@ -1,53 +0,0 @@ -# pause Until - -Pause the current part of the program until a condition becomes true. - -```sig -pauseUntil(() => true) -``` - -Sometimes you need to wait in one part of a program for something to happen somewhere else in the program. This is done by pausing until some condition elsewhere becomes ``true``. Such a condition could be a value you set in an event block or a function that returns a [boolean](/types/boolean) . - -## Parameters - -* **condition**: a [boolean](/types/boolean) condition that restarts the program when it becomes ``true``. -* **timeOut**: an optional paramenter which is a [number](/types/number) of milliseconds to wait for the **condition** to become ``true``. The pause ends when the timeout has elapsed even if **condition** is still ``false``. - -## ~hint - -The code you have in **events** or inside **runInParallel** blocks will continue to execute while the current part of your program is paused. - -## ~ - -## Examples #example - -### Timer in a parallel block #ex1 - -Make a `5` second timer by counting time in a parallel code section. - -```blocks -let msecs = 0 -control.runInParallel(function () { - while (true) { - control.waitMicros(1000) - msecs += 1 - } -}) -pauseUntil(() => msecs > 5000) -``` - -### Timer in a boolean function #ex2 - -Wait on a five second timer function. - -```typescript -function waitFiveSeconds() : boolean { - for (let i = 0; i < 5000; i++) { - control.waitMicros(1000) - } - return true -} -pauseUntil(() => waitFiveSeconds()) -``` - -## #seealso \ No newline at end of file diff --git a/libs/base/docs/device/error-codes.md b/libs/base/docs/device/error-codes.md deleted file mode 100644 index 335eb0a1..00000000 --- a/libs/base/docs/device/error-codes.md +++ /dev/null @@ -1,53 +0,0 @@ -# Error codes - -## #error-info - -Your @boardname@ may encounter a situation that prevents it from running your code. The system software that runs the programs on your board may notify you that an error occurred. It might show this error as a numeric code on the display, LEDs, or as output on a data port. These are called _panic_ codes. When an error happens that causes a panic code, your program will stop and you'll need to reset the board to start again. - -## Panic codes - -Some panic codes are for general errors that might occur while your program runs. Other times, a device or resource you want to use isn't present or isn't working and you receive a panic code for that. Several panic codes are related to the use of memory and accessing data in it. - -* **20** (`PANIC_CODAL_OOM`): there is no free memory on the @boardname@ -* **21** (`PANIC_GC_OOM`): Garbage Collection can't allocate any more memory -* **22** (`PANIC_GC_TOO_BIG_ALLOCATION`): Garbage Collection can't allocate memory for the requested size -* **30** (`PANIC_CODAL_HEAP_ERROR`): a general memory allocation error -* **40** (`PANIC_CODAL_NULL_DEREFERENCE`): a memory pointer is NULL and points to an invalid location -* **50** (`PANIC_CODAL_USB_ERROR`): USB is not available or can't initialize, transmit, or receive -* **90** (`PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR`): actual board hardware doesn't match the configuration description -* **901** (`PANIC_INVALID_BINARY_HEADER`): the type header for the object is not valid -* **902** (`PANIC_OUT_OF_BOUNDS`): the object data portion is greater than the length defined for it -* **903** (`PANIC_REF_DELETED`): an object reference was deleted and the object is no longer valid -* **904** (`PANIC_SIZE`): the object size doesn't match the size defined for the type -* **905** (`PANIC_INVALID_VTABLE`): an object vtable is invalid or not initialized -* **906** (`PANIC_INTERNAL_ERROR`): an internal resource error -* **907** (`PANIC_NO_SUCH_CONFIG`): the specified device resource is not present -* **908** (`NO_SUCH_PIN`): the specified pin is not present on the board -* **909** (`PANIC_INVALID_ARGUMENT`): the argument value is out of range or the type or format is invalid -* **910** (`PANIC_MEMORY_LIMIT_EXCEEDED`): insufficient memory is available to satisfy and allocation request -* **911** (`PANIC_SCREEN_ERROR`): the screen isn't present or it can't properly display the output -* **912** (`PANIC_MISSING_PROPERTY`): the property requested is not present in the current object -* **913** (`PANIC_INVALID_IMAGE`): the data for a screen image data is invalid or formatted incorrectly -* **914** (`PANIC_CALLED_FROM_ISR`): the current code isn't allowed to run in an interrupt service routine (ISR) -* **915** (`PANIC_HEAP_DUMPED`): the contents of memory was output to a debug port -* **916** (`PANIC_STACK_OVERFLOW`): stack size limit for the fiber was exceeded -* **917** (`PANIC_BLOCKING_TO_STRING`): inline execution blocked due to an existing resume context -* **918** (`PANIC_VM_ERROR`): VM execution context error -* **920** (`PANIC_SETTINGS_CLEARED`): storage required for system settings, user settings were cleared -* **921** (`PANIC_SETTINGS_OVERLOAD`): frequency of writes to settings storage is too high -* **922** (`PANIC_SETTINGS_SECRET_MISSING`): settings storage in flash memory is inconsistent -* **923** (`PANIC_DELETE_ON_CLASS`): a settings key delete was attempted on a class -* **924** (`PANIC_OUT_OF_TIMERS`): no more timers are available -* **980** (`PANIC_CAST_FROM_UNDEFINED`): attempted cast from an `undefined` value to another type -* **981** (`PANIC_CAST_FROM_BOOLEAN`): attempted cast from a [boolean](/types/boolean) value to an incompatible type -* **982** (`PANIC_CAST_FROM_NUMBER`): attempted cast from a [number](/types) value to an incompatible type or no conversion is available -* **983** (`PANIC_CAST_FROM_STRING`): attempted cast from a [string](/types/string) value to an incompatible type or no conversion is available -* **984** (`PANIC_CAST_FROM_OBJECT`): attempted cast from an object to an incompatible type -* **985** (`PANIC_CAST_FROM_FUNCTION`): attempted cast from a function to a non-function type -* **989** (`PANIC_CAST_FROM_NULL`): attempted cast from a `null` value to another type - -## #specific - -## See also - -[panic](/reference/control/panic), [assert](/reference/control/assert) diff --git a/libs/base/docs/reference/console.md b/libs/base/docs/reference/console.md deleted file mode 100644 index 0bf10cc2..00000000 --- a/libs/base/docs/reference/console.md +++ /dev/null @@ -1,13 +0,0 @@ -# Console - -Output text and data values to the console. - -```cards -console.log(""); -console.logValue("x", 0); -``` - -## See also - -[log](/reference/console/log), -[log value](/reference/console/log-value) \ No newline at end of file diff --git a/libs/base/docs/reference/console/log-value.md b/libs/base/docs/reference/console/log-value.md deleted file mode 100644 index 48553717..00000000 --- a/libs/base/docs/reference/console/log-value.md +++ /dev/null @@ -1,38 +0,0 @@ -# log value - -Write a **name:value** pair as a line of text to the console output. - -```sig -console.logValue("x", 0); -``` - -A **name:value** pair is a string that has both a name for a value and the value -itself. If you want to send a temperature value of 32 degrees as a _name:value_ pair, -it would go to the console output as this: "temperature:32". This is a good way to -connect a number value to its meaning. - -So, ``||console:log value||`` does this but you give the name and the value as two parts and it -sends it as a pair. - -## Parameters - -* **name**: a [string](/types/string) that is the name part of the _name:value_ pair -* **value**: a [number](/types/number) that is the value part of the _name:value_ pair - -## Example #example - -Send _name:value_ pairs for odd and even numbers to the console output. - -```blocks -for (let i = 0; i < 10; i++) { - if (i % 2 > 0) { - console.logValue("odd", i) - } else { - console.logValue("even", i) - } -} -``` - -## See also #seealso - -[log](/reference/console/log) \ No newline at end of file diff --git a/libs/base/docs/reference/console/log.md b/libs/base/docs/reference/console/log.md deleted file mode 100644 index ec910439..00000000 --- a/libs/base/docs/reference/console/log.md +++ /dev/null @@ -1,33 +0,0 @@ -# log - -Write a line of text to the console output. - -```sig -console.log(""); -``` - -A line of text is a string that has two special characters added at the end: _carriage return_ -and _line feed_. These characters are really just codes that mean start a new line. -Sometimes they appear in code as ``"\r\n"``. - -After using ``||console:log||``, any new text written to the console output will begin on a new line. - -With ``||console:log||``, the new line characters are automatically added for you. You only need to give the text you want to write. - -## Parameters - -* **text**: the [string](/types/string) to write to the console output. - -## Example #example - -Write two greeting messages to the console output. - -```blocks -console.log("How are you today?"); -pause(5000); -console.log("Well that's great! I'm doing well too."); -``` - -## See also #seealso - -[log value](/reference/console/log-value) \ No newline at end of file diff --git a/libs/base/docs/reference/control.md b/libs/base/docs/reference/control.md deleted file mode 100644 index cca81f9a..00000000 --- a/libs/base/docs/reference/control.md +++ /dev/null @@ -1,25 +0,0 @@ -# Control - -Program controls and events. - -```cards -control.millis(); -control.runInParallel(() => { - -}); -control.reset(); -control.waitMicros(4); -control.deviceSerialNumber(); -``` - -## Advanced #advanced - -```cards -control.raiseEvent(0, 0); -control.onEvent(0, 0, () => { - -}); -control.assert(false, 0); -control.deviceDalVersion(); -control.panic(0); -``` diff --git a/libs/base/docs/reference/control/assert.md b/libs/base/docs/reference/control/assert.md deleted file mode 100644 index 8c3c16ff..00000000 --- a/libs/base/docs/reference/control/assert.md +++ /dev/null @@ -1,33 +0,0 @@ -# assert - -Display an error number and stop the program if the assertion condition is false. - -```sig -control.assert(false, 0) -``` - -You can insist that your program will stop at an assert block if a certain condition you check is false. The error number in the assert is written to the serial port with a failure message. - -## Parameters - -* **cond**: a [boolean](/types/boolean) where true means everything is ok or false which means, stop the program! -* **code**: an error [number](/types/number) you match to an error situation in your program. - -## Example #example - -Stop the program if a sensor connected to pin `A0` sends a low (`0`) signal. - -```blocks -forever(function () { - control.assert((pins.A0.digitalRead() == 1), 15) - pause(1000) -}) -``` - -## See also #seealso - -[panic](/reference/control/panic) - -```package -base -``` \ No newline at end of file diff --git a/libs/base/docs/reference/control/device-dal-version.md b/libs/base/docs/reference/control/device-dal-version.md deleted file mode 100644 index adec6fc5..00000000 --- a/libs/base/docs/reference/control/device-dal-version.md +++ /dev/null @@ -1,25 +0,0 @@ -# device Dal Version - -Get the version information for the system software on the @boardname@. - -```sig -control.deviceDalVersion() -``` - -## Returns - -* a [string](/types/string) that represents the version of the system software (DAL) on the board. - -Returns `"sim"` when running the simulator, and `"linux"` when running on Raspberry Pi. - -## Example #example - -Write the system software version to the serial port. - -```blocks -serial.writeLine("DAL version = " + control.deviceDalVersion()); -``` - -## See also #seealso - -[device serial number](/reference/control/device-serial-number) diff --git a/libs/base/docs/reference/control/device-serial-number.md b/libs/base/docs/reference/control/device-serial-number.md deleted file mode 100644 index 871ad9ba..00000000 --- a/libs/base/docs/reference/control/device-serial-number.md +++ /dev/null @@ -1,25 +0,0 @@ -# device Serial Number - -Get the serial number for the @boardname@ - -```sig -control.deviceSerialNumber() -``` - -The system software in your board creates a unique number to identify the board. You can use this number in your program if you want to know which board is running your program. - -## Returns - -* a [number](/types/number) that is created to uniquely identify this board. - -## Example #example - -Write the board serial number to the serial port. - -```blocks -serial.writeValue("serialnumber", control.deviceSerialNumber()); -``` - -## See also #seealso - -[device dal version](/reference/control/device-dal-version) \ No newline at end of file diff --git a/libs/base/docs/reference/control/millis.md b/libs/base/docs/reference/control/millis.md deleted file mode 100644 index ed531c13..00000000 --- a/libs/base/docs/reference/control/millis.md +++ /dev/null @@ -1,25 +0,0 @@ -# millis - -Get the number of milliseconds of time passed since the board was turned on. - -```sig -control.millis() -``` - -## Returns - -* the [number](/types/number) of milliseconds of time since the board was turned on. - -## Example #example - -Find how many days, hours, minutes, and seconds the @boardname@ has been running. - -```blocks -let msecs = control.millis() -let seconds = msecs / 1000 -let mins = seconds / 60 -let hours = mins / 60 -let days = hours / 24 -``` - -## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/on-event.md b/libs/base/docs/reference/control/on-event.md deleted file mode 100644 index 07499cf1..00000000 --- a/libs/base/docs/reference/control/on-event.md +++ /dev/null @@ -1,93 +0,0 @@ -# on Event - -Run some code when a registered event happens. - -```sig -control.onEvent(0, 0, () => {}) -``` -Instead of waiting inside of a loop that is part the main program, an event block is -a good way to have some extra code respond to something that happens with the board or -in your program. - -It works like this: some code in another part of the program decides it wants to announce -that something special or important just happened. It does this by _raising_ an _event_. -Some other code is placed inside an ``||control:on event||`` block. The ``||control:on event||`` block _registers_ -itself to run when a matching event is _raised_. - -Your program decides what an event should be and makes it official by _registering_ the event along with -a source identification number (id), **src**. The id in **src** is a way to know what **_thing_** is causing an event, -like a sensor, or some special time period that is now over. The **value** tells what the cause of the -event is. - -### Why use events? - -If you want to run some code when a status changes, you might do it this way -in the main part of the program: - -```blocks -let nowStatus = false -control.runInParallel(() => { - control.waitMicros(10000) - nowStatus = true -}) - -let lastStatus = nowStatus; -while(lastStatus == nowStatus) { - control.waitMicros(1000) -} -``` -The [``||loops:while||``](/blocks/loops/while) loop checks for a change in `nowStatus`. The problem is that your program is stuck -in the loop until `nowStatus` changes and it can't do any more work until then. - -But, we can change the program to use an event instead of waiting in a loop. Let's register an event -and give it a source identifier, or **src**, of `15` and a cause **value** of `1`: - -```blocks -let because = 0; -control.runInParallel(() => { - control.waitMicros(100000) - control.raiseEvent(15, 1) -}) - -control.onEvent(15, 1, () => { - because = 1; -}) -``` - -So, you see that the program registered an event known as `15`, `1`. The source is known by `15` and the -cause of the event is `1`. Why use these numbers? Well, let's say that you have a moisture sensor connected -to your board. You could make it known to your program that any event that comes from a source of `15` is about your sensor. You can say that a cause of `1` means things are too dry. - -## Parameters - -* **src**: the identification [number](/types/number) (the source) of this event, such as: `10`. -* **value**: a [number](/types/number) that tells what the cause of the event is, like: `4`. -* **handler**: the code to run when the event happens. - -## Example #example - -Register two events coming from source `22`. Write to the console when -the events of `0` and `1` are _raised_. - -```blocks -const myNotify = 22 - -control.runInParallel(function() { - for (let i = 0; i < 2; i++) { - pause(1000) - control.raiseEvent(myNotify, i) - } -}) - -control.onEvent(myNotify, 0, () => { - console.logValue("myNotify", 0) -}) - -control.onEvent(myNotify, 1, () => { - console.logValue("myNotify", 1) -}) -``` - -## See also ##seealso - -[raise event](/reference/control/raise-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/panic.md b/libs/base/docs/reference/control/panic.md deleted file mode 100644 index 93479d3c..00000000 --- a/libs/base/docs/reference/control/panic.md +++ /dev/null @@ -1,37 +0,0 @@ -# panic - -Display an error number and stop the program. - -```sig -control.panic(0) -``` - -If your board has some way to display error information, ``||panic||`` will work -with it to show error numbers. - -Your program stops when you use ``||panic||``. Use this when you think something bad enough has -happened and your program can't run properly anymore. - -## Parameters - -* **code**: an error [number](/types/number) you match to an error situation in your program. - -## Example #example - -Send a 'code red' error that you created to the error display if the input from pin `A0` is -lower than `10`. - -```blocks -let codeRed = 1 -let codeBlue = 2 - -if (pins.A0.analogRead() < 10) { - control.panic(codeRed) -} -``` - -## See also #seealso - -[assert](/reference/control/assert) - -[Error Codes](/device/error-codes) \ No newline at end of file diff --git a/libs/base/docs/reference/control/raise-event.md b/libs/base/docs/reference/control/raise-event.md deleted file mode 100644 index 4aa3cbc6..00000000 --- a/libs/base/docs/reference/control/raise-event.md +++ /dev/null @@ -1,61 +0,0 @@ -# raise Event - -Announce that something happened at an event source. - -```sig -control.raiseEvent(0, 0) -``` -You use ``||control:raise event||`` to announce that something happened with the board or something special -happened in your program. You do this if there are other parts of your program that might want -to know about it. - -If you've added some [``||control:on event||``](/reference/control/on-event) blocks to your program, -the code inside them will run if the **src** and **value** numbers are the same as those with -``||control:raise event||``. The **src** tells about where the event is coming from. You pick a number -for it to identify something like a sensor or a special situation in your program. If you want -to announce that it's getting dark, you can make **src** something like `51` for the light sensor's -source number. This means that anything you want to announce about the light sensor, you raise -event with `51`. - -Many events can happen to a single source (**src**). With the light sensor you can announce that -its getting darker or lighter. This is the cause of the event, the **value**. So, for the light -sensor (the source number `51`) you might add two events for **value**: `1` for darker and `2` for lighter. - -With the light sensor example, you tell the program that it's getting darker: - -```block -control.raiseEvent(51, 1) -``` - -## Parameters - -* **src**: the identification [number](/types/number) (the source) of this event, such as: `10`. -* **value**: a [number](/types/number) tells what the cause of the event is, like: `4`. - -## Example #example - -Register two events coming from source `22`. Write to the console when -the events of `0` and `1` are _raised_. - -```blocks -const myNotify = 22; - -control.runInParallel(function() { - for (let i = 0; i < 2; i++) { - pause(1000); - control.raiseEvent(myNotify, i); - } -}) - -control.onEvent(myNotify, 0, () => { - console.logValue("myNotify", 0) -}) - -control.onEvent(myNotify, 1, () => { - console.logValue("myNotify", 1) -}) -``` - -## See also #seealso - -[on event](/reference/control/on-event), [wait for event](/reference/control/wait-for-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/reset.md b/libs/base/docs/reference/control/reset.md deleted file mode 100644 index 9c845fca..00000000 --- a/libs/base/docs/reference/control/reset.md +++ /dev/null @@ -1,20 +0,0 @@ -# reset - -Reset the board and start the program from the beginning. - -```sig -control.reset() -``` - -Everything that the program did with the board is set back to the way it was before the -program started. The program starts over again from the beginning. - -## Example #example - -Reset the board and begin again. - -```blocks -control.reset() -``` - -## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/run-in-background.md b/libs/base/docs/reference/control/run-in-background.md deleted file mode 100644 index 169d410f..00000000 --- a/libs/base/docs/reference/control/run-in-background.md +++ /dev/null @@ -1,3 +0,0 @@ -# run In Background - -This function is deprecated and replaced by [run in parallel](/reference/control/run-in-parallel). \ No newline at end of file diff --git a/libs/base/docs/reference/control/run-in-parallel.md b/libs/base/docs/reference/control/run-in-parallel.md deleted file mode 100644 index 80014099..00000000 --- a/libs/base/docs/reference/control/run-in-parallel.md +++ /dev/null @@ -1,75 +0,0 @@ -# run In Parallel - -Run some other code at the same time that your main program code runs. - -```sig -control.runInParallel(() => {}) -``` - -Sometimes you want your program to work on more than one thing at a time. The main part of your program is -always put in [``||on start||``](/blocks/on-start). But, you can also put some other part of your -program in ``||control:run in parallel||``. This is useful when you want your program to keep doing important things -and you don't want to wait for some other actions to happen first. - -## Separate tasks #tasks - -As an example, you could have a small task to rotate a bit in a 16 character -string of zeros. This is placed inside a ``||control:run in parallel||`` block: - -```blocks -let bitPos = 0 -let rorit = true -let zeros = "" - -control.runInParallel(function() { - while (rorit) { - if (bitPos > 15) { - bitPos = 0 - } - zeros = "" - for (let i = 0; i < 16; i++) { - if (bitPos == i) { - zeros = zeros + "1" - } else { - zeros = zeros + "0" - } - } - console.log(zeros) - pause(200) - } -}) -``` - -Code is added to the main part of the program to turn the bit rotation on, pause for `5` seconds and then turn it off. It pauses for another `5` seconds and then trys to turn the bit rotation back on. However, the parallel task has finished and -the bit rotation won't start again. - -```blocks -let rorit = true -pause(5000) -rorit = false -pause(5000) -rorit = true -``` - -## Parameters - -* **a**: the code to run in the background. - -## Example #example - -Use a parallel task to generate a magic number. In the main program check the value of the magic number twice. The first time check the value right away. The -second time, check `2` seconds later after the parallel task has time to run. - -```blocks -let magic = 0 - -control.runInParallel(function() { - magic = Math.randomRange(1000, 5000) -}) - -console.logValue("magic", magic) -pause(2000) -console.logValue("magic", magic) -``` - -## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/control/wait-for-event.md b/libs/base/docs/reference/control/wait-for-event.md deleted file mode 100644 index c10a8fea..00000000 --- a/libs/base/docs/reference/control/wait-for-event.md +++ /dev/null @@ -1,63 +0,0 @@ -# wait For Event - -Stop running the current code and wait for an event. - -```sig -control.waitForEvent(0, 0) -``` -You might want your code to stop for a while until some event you're expecting happens. -If you want your code to pause until a known event happens, use a ``||control:wait for event||`` block. -A known event is something you identify that happens on the board or in your program. -An event has both a source and a cause. The source is where the event comes from, like a sensor or -some condition in your program. The cause is what made the event happen at the source. - -You assign numbers for your event sources and causes. These numbers are used by [``||control:raise event||``](/reference/control/raise-event) to announce to your program that an event just happened. - -As an example, you could make a timer that always causes an event every 100 milliseconds. The source -number for the timer is `6` and the cause value is `1`. The program could wait for one of the time -events like this: - -```blocks -const myTimer = 6; -const timerTimeout = 1; - -control.runInParallel(function() { - while (true) { - control.waitMicros(100000) - control.raiseEvent(myTimer, timerTimeout) - } -}) - -control.waitForEvent(myTimer, timerTimeout) -``` - -## Parameters - -* **id**: the identification [number](/types/number) (the source) of this event, such as: `10`. -* **value**: a [number](/types/number) tells what the cause of the event is, like: `4`. - -## Example #example - -Make a timeout timer to signal every 2 seconds. Wait two times and write to the -console each time. - -```blocks -const myTimer = 6; -const timerTimeout = 1; - -control.runInParallel(function() { - while (true) { - pause(2000) - control.raiseEvent(myTimer, timerTimeout) - } -}) - -control.waitForEvent(myTimer, timerTimeout) -console.log("Timer timeout") -control.waitForEvent(myTimer, timerTimeout) -console.log("Timer timeout") -``` - -## See also #seealso - -[raise event](/reference/control/raise-event), [on event](/reference/control/on-event) \ No newline at end of file diff --git a/libs/base/docs/reference/control/wait-micros.md b/libs/base/docs/reference/control/wait-micros.md deleted file mode 100644 index 21b0b557..00000000 --- a/libs/base/docs/reference/control/wait-micros.md +++ /dev/null @@ -1,26 +0,0 @@ -# wait Micros - -Make the part of the program running right now wait for some number of microseconds. - -```sig -control.waitMicros(10) -``` -The code inside the current block, such as a ``||on start||``, ``||control:run in parallel||``, and -``||control:on event||`` , waits for some amount of time. The time number is in microseconds (one-millionth of a second). - -## Parameters - -* **micros**: the [number](/types/number) of microseconds for this block of code to wait for. - -## Example #example - -Turn on an a sensor that has a control signal connected to pin `D4`. Wait `20` microseconds -for the sensor to detect something, then read the sensor value on pin `A4`. - -```blocks -pins.D4.digitalWrite(true) -control.waitMicros(20) -let temperature = pins.A4.analogRead() -``` - -## #seealso \ No newline at end of file diff --git a/libs/base/docs/reference/input.md b/libs/base/docs/reference/input.md deleted file mode 100644 index 7d410da1..00000000 --- a/libs/base/docs/reference/input.md +++ /dev/null @@ -1,53 +0,0 @@ -# Input - -Events and data from sensors - -## Accelerometer #acceleration - -```cards -input.onGesture(Gesture.Shake, () => { - -}) -input.setAccelerometerRange(AcceleratorRange.OneG) -input.acceleration(Dimension.X) -input.rotation(Rotation.Pitch) - -``` - -## Light sensor #lightsensor - -```cards -input.onLightConditionChanged(LightCondition.Dark, () => { - -}) -input.lightLevel() -``` - -## Buttons #buttons - -```cards -input.buttonA.isPressed() -input.buttonA.wasPressed() -input.onSwitchMoved(SwitchDirection.Left, () => { - -}) -input.buttonA.onEvent(ButtonEvent.Click, () => { - -}) -``` - -## Microphone #microphone - -```cards -input.onLoudSound(() => {}) -input.soundLevel() -``` - -## Thermometer #thermometer - -```cards -input.onTemperatureConditionChanged(TemperatureCondition.Hot, 15, TemperatureUnit.Celsius, () => { - -}) -input.temperature(TemperatureUnit.Celsius) -``` diff --git a/libs/base/docs/reference/loops/forever.md b/libs/base/docs/reference/loops/forever.md deleted file mode 100644 index 2cb1f480..00000000 --- a/libs/base/docs/reference/loops/forever.md +++ /dev/null @@ -1,33 +0,0 @@ -# forever - -Run a part of the program in the background and keep running it over again. - -```sig -forever(() => { -}) -``` - -The code you have in a ``||loops:forever||`` loop will run and keep repeating itself the whole time your -program is active. Code in other parts of your program won't stop while your ``||loops:forever||`` -loop is running. This includes other ``||loops:forever||`` loops and the [``||control:run in parallel||``](/reference/control/run-in-parallel) block. - -## Parameters - -* **a**: the code to keep running over and over again. - -## Example #example - -Create an mood generator that writes a current mood to the console every `5` seconds. - -```blocks -let mood = ["happy", "sad", "joyful", "angry"] -forever(function () { - console.log("mood = " + mood[Math.randomRange(0, 3)]) - pause(5000) -}) -``` - -## See also #seealso - -[while](/blocks/loops/while), [repeat](/blocks/loops/repeat), -[run in parallel](/reference/control/run-in-parallel) diff --git a/libs/base/docs/reference/loops/pause.md b/libs/base/docs/reference/loops/pause.md deleted file mode 100644 index 0d902561..00000000 --- a/libs/base/docs/reference/loops/pause.md +++ /dev/null @@ -1,31 +0,0 @@ -# pause - -Pause a part of the program for some number of milliseconds. - -```sig -pause(400) -``` - -When code in a block comes to a ``||control:pause||``, it will wait the amount of time you tell it to. Code -in blocks like ``||loops:forever||`` and ``||control:run in parallel||`` will keep running while code in some other -block is waiting at a ``||control:pause||``. - -## Parameters - -* **ms**: the [number](/types/number) of milliseconds that you want to pause for. So, 100 milliseconds = 1/10 second, and 1000 milliseconds = 1 second. - -## Example #example - -Write the first five natural numbers to the console but wait one-half second between each write. - -```blocks -for (let i = 0; i < 5; i++) { - console.logValue("naturals", i + 1) - pause(500) -} -``` - -## See also #seealso - -[while](/blocks/loops/while), [for](/blocks/loops/for), -[forever](/reference/loops/forever) diff --git a/libs/base/docs/reference/text/convert-to-text.md b/libs/base/docs/reference/text/convert-to-text.md deleted file mode 100644 index 5cf823c2..00000000 --- a/libs/base/docs/reference/text/convert-to-text.md +++ /dev/null @@ -1,34 +0,0 @@ -# convert to text - -Change the value of any [type](/types) into a text [string](/types/string). - -```sig -convertToText(123) -``` - -## Parameters - -* **value**: a value of some [type](/types) to convert to a [string](/types/string). - -## Returns - -* a [string](/types/string) that is a text representation of **value**. - -## Example #example - -Convert a boolean and a number value into strings and join them in a sentence. - -```blocks -let myBoolean = false -let myNumber = 0 - -myBoolean = true -myNumber = 123 - -let myString = "It is " + convertToText(myBoolean) + " that " + convertToText(myNumber) + " is now a string!" -``` - -## Sea also #seealso - -[parse int](/reference/text/parse-int), -[parse float](/reference/text/parse-float) diff --git a/libs/base/eventcontext.ts b/libs/base/eventcontext.ts deleted file mode 100644 index 8c270f09..00000000 --- a/libs/base/eventcontext.ts +++ /dev/null @@ -1,289 +0,0 @@ -namespace control { - /** - * Run code when a registered event happens. - * @param id the event compoent id - * @param value the event value to match - */ - //% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src|with value %value" - //% blockExternalInputs=1 - //% help="control/on-event" - export function onEvent(src: number, value: number, handler: () => void, flags = 16) { // EVENT_LISTENER_DEFAULT_FLAGS - const ctx = control.eventContext(); - if (!ctx) - control.internalOnEvent(src, value, handler, flags); - else - ctx.registerHandler(src, value, handler, flags); - } - - export class FrameCallback { - order: number - handler: () => void - } - - class EventHandler { - constructor( - public src: number, - public value: number, - public handler: () => void, - public flags: number - ) { } - - register() { - control.internalOnEvent(this.src, this.value, () => { - if (this.handler) this.handler(); - }, this.flags) - } - - unregister() { - control.internalOnEvent(this.src, this.value, doNothing, this.flags); - } - } - - function doNothing() { } - - - - export class EventContext { - private handlers: EventHandler[]; - private frameCallbacks: FrameCallback[]; - private frameWorker: number; - private framesInSample: number; - private timeInSample: number; - public deltaTimeMillis: number; - private prevTimeMillis: number; - private idleCallbacks: (() => void)[]; - - static lastStats: string; - static onStats: (stats: string) => void; - - constructor() { - this.handlers = []; - this.framesInSample = 0; - this.timeInSample = 0; - this.deltaTimeMillis = 0; - this.frameWorker = 0; - this.idleCallbacks = undefined; - if (!EventContext.lastStats) { - EventContext.lastStats = ""; - } - } - - get deltaTime() { - return this.deltaTimeMillis / 1000; - } - - private runCallbacks() { - control.enablePerfCounter("all frame callbacks") - - let loopStart = control.millis() - this.deltaTimeMillis = loopStart - this.prevTimeMillis; - this.prevTimeMillis = loopStart; - for (let f of this.frameCallbacks) { - f.handler() - } - let runtime = control.millis() - loopStart - this.timeInSample += runtime - this.framesInSample++ - if (this.timeInSample > 1000 || this.framesInSample > 30) { - const fps = this.framesInSample / (this.timeInSample / 1000); - EventContext.lastStats = `fps:${Math.round(fps)}`; - if (fps < 99) - EventContext.lastStats += "." + (Math.round(fps * 10) % 10) - if (control.ramSize() > 2000000 && control.profilingEnabled()) { - control.dmesg(`${(fps * 100) | 0}/100 fps - ${this.framesInSample} frames`) - control.gc() - control.dmesgPerfCounters() - } - this.timeInSample = 0 - this.framesInSample = 0 - } - let delay = Math.max(1, 20 - runtime) - - return delay - } - - private runningCallbacks: boolean; - private registerFrameCallbacks() { - if (!this.frameCallbacks) return; - - const worker = this.frameWorker; - control.runInParallel(() => { - if (this.runningCallbacks) { - // this context is still running in a different fiber; - // delay until the other fiber doing so has ceased. - pauseUntil(() => !this.runningCallbacks); - } - this.runningCallbacks = true; - - this.framesInSample = 0; - this.timeInSample = 0; - this.deltaTimeMillis = 0; - this.prevTimeMillis = control.millis(); - - while (worker == this.frameWorker) { - let delay = this.runCallbacks() - pause(delay) - } - - this.runningCallbacks = false; - }) - } - - register() { - for (const h of this.handlers) - h.register(); - this.registerFrameCallbacks(); - } - - unregister() { - for (const h of this.handlers) - h.unregister(); - this.frameWorker++; - } - - registerFrameHandler(order: number, handler: () => void): FrameCallback { - if (!this.frameCallbacks) { - this.frameCallbacks = []; - this.registerFrameCallbacks(); - } - - const fn = new FrameCallback() - fn.order = order - fn.handler = handler - for (let i = 0; i < this.frameCallbacks.length; ++i) { - if (this.frameCallbacks[i].order > order) { - this.frameCallbacks.insertAt(i, fn) - return fn; - } - } - this.frameCallbacks.push(fn); - return fn; - } - - unregisterFrameHandler(fn: FrameCallback) { - if (!fn || !this.frameCallbacks) return; - const i = this.frameCallbacks.indexOf(fn); - if (i > -1) - this.frameCallbacks.splice(i, 1); - } - - registerHandler(src: number, value: number, handler: () => void, flags: number) { - // already there? - for (const h of this.handlers) { - if (h.src == src && h.value == value) { - h.flags = flags; - h.handler = handler; - return; - } - } - // register and push - const hn = new EventHandler(src, value, handler, flags); - this.handlers.push(hn); - hn.register(); - } - - addIdleHandler(handler: () => void) { - if (!this.idleCallbacks) { - this.idleCallbacks = []; - this.registerHandler(15/*DAL.DEVICE_ID_SCHEDULER*/, 2/*DAL.DEVICE_SCHEDULER_EVT_IDLE*/, () => this.runIdleHandler(), 16); - } - this.idleCallbacks.push(handler); - } - - removeIdleHandler(handler: () => void) { - if (handler && this.idleCallbacks) - this.idleCallbacks.removeElement(handler); - } - - private runIdleHandler() { - if (this.idleCallbacks) { - const ics = this.idleCallbacks.slice(0); - ics.forEach(ic => ic()); - } - } - } - let eventContexts: EventContext[]; - - /** - * Gets the current event context if any - */ - export function eventContext(): EventContext { - return eventContexts ? eventContexts[eventContexts.length - 1] : undefined; - } - - /** - * Pushes a new event context and clears all handlers - */ - export function pushEventContext(): EventContext { - if (!eventContexts) - eventContexts = []; - - // unregister previous context - const ctx = eventContext(); - if (ctx) ctx.unregister(); - // register again - const n = new EventContext(); - eventContexts.push(n); - return n; - } - - /** - * Pops the current event context and restore handlers if any previous context - */ - export function popEventContext() { - if (!eventContexts) return; - - // clear current context - const ctx = eventContexts.pop(); - if (!ctx) return; - ctx.unregister(); - - // register old context again - const context = eventContexts[eventContexts.length - 1]; - if (context) - context.register(); - else - eventContexts = undefined; - } - - let _idleCallbacks: (() => void)[]; - /** - * Registers a function to run when the device is idling - * @param handler - */ - export function onIdle(handler: () => void) { - if (!handler) return; - - const ctx = eventContext(); - if (ctx) ctx.addIdleHandler(handler); - else { - if (!_idleCallbacks) { - _idleCallbacks = []; - control.runInBackground(function () { - while (_idleCallbacks) { - _idleCallbacks.slice(0).forEach(cb => cb()); - pause(20); - } - }) - /* - control.internalOnEvent( - 15. // DAL.DEVICE_ID_SCHEDULER - 2, // DAL.DEVICE_SCHEDULER_EVT_IDLE - function() { - pins.LED.digitalWrite(on = !on); - if (_idleCallbacks) - _idleCallbacks.slice(0).forEach(cb => cb()); - }, 192); // MESSAGE_BUS_LISTENER_IMMEDIATE - */ - } - _idleCallbacks.push(handler); - } - } - - export function removeIdleHandler(handler: () => void) { - if (!handler) return; - const ctx = eventContext(); - if (ctx) ctx.removeIdleHandler(handler); - else if (_idleCallbacks) _idleCallbacks.removeElement(handler); - } -} \ No newline at end of file diff --git a/libs/base/fixed.ts b/libs/base/fixed.ts deleted file mode 100644 index 1c3f8409..00000000 --- a/libs/base/fixed.ts +++ /dev/null @@ -1,75 +0,0 @@ -interface Fx8 { - _dummyFx8: string; -} - -function Fx8(v: number) { - return ((v * 256) | 0) as any as Fx8 -} - -namespace Fx { - export const zeroFx8 = 0 as any as Fx8 - export const oneHalfFx8 = 128 as any as Fx8 - export const oneFx8 = 256 as any as Fx8 - export const twoFx8 = 512 as any as Fx8 - - export function neg(a: Fx8) { - return (-(a as any as number)) as any as Fx8 - } - export function toIntShifted(a: Fx8, n: number) { - return (a as any as number) >> (n + 8) - } - export function add(a: Fx8, b: Fx8) { - return ((a as any as number) + (b as any as number)) as any as Fx8 - } - export function iadd(a: number, b: Fx8) { - return ((a << 8) + (b as any as number)) as any as Fx8 - } - export function sub(a: Fx8, b: Fx8) { - return ((a as any as number) - (b as any as number)) as any as Fx8 - } - export function mul(a: Fx8, b: Fx8) { - return (Math.imul((a as any as number), (b as any as number)) >> 8) as any as Fx8 - } - export function imul(a: Fx8, b: number) { - return Math.imul((a as any as number), (b as any as number)) as any as Fx8 - } - export function div(a: Fx8, b: Fx8) { - return Math.idiv((a as any as number) << 8, b as any as number) as any as Fx8 - } - export function idiv(a: Fx8, b: number) { - return Math.idiv((a as any as number), b) as any as Fx8 - } - export function compare(a: Fx8, b: Fx8) { - return (a as any as number) - (b as any as number) - } - export function abs(a: Fx8) { - if ((a as any as number) < 0) - return (-(a as any as number)) as any as Fx8 - else - return a - } - export function min(a: Fx8, b: Fx8) { - if (a < b) - return a - else - return b - } - export function max(a: Fx8, b: Fx8) { - if (a > b) - return a - else - return b - } - export function leftShift(a: Fx8, n: number) { - return (a as any as number << n) as any as Fx8 - } - export function rightShift(a: Fx8, n: number) { - return (a as any as number >> n) as any as Fx8 - } - export function toInt(v: Fx8) { - return ((v as any as number) + 128) >> 8 - } - export function toFloat(v: Fx8) { - return (v as any as number) / 256 - } -} \ No newline at end of file diff --git a/libs/base/forever.ts b/libs/base/forever.ts deleted file mode 100644 index 44b42c8f..00000000 --- a/libs/base/forever.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Repeats the code forever in the background. On each iteration, allows other codes to run. - * @param body code to execute - */ -//% help=loops/forever weight=100 afterOnStart=true blockNamespace="loops" -//% blockId=forever block="forever" blockAllowMultiple=1 -function forever(a: () => void): void { - loops.forever(a); -} - -// micro:bit compatibility -// these functions allow some level of reuse -// between micro:bit and other maker-style editors -namespace basic { - export function forever(a: () => void) { - loops.forever(a); - } -} \ No newline at end of file diff --git a/libs/base/gc.cpp b/libs/base/gc.cpp deleted file mode 100644 index d0834ec5..00000000 --- a/libs/base/gc.cpp +++ /dev/null @@ -1,907 +0,0 @@ -#include "pxtbase.h" - -#ifndef GC_BLOCK_SIZE -#define GC_BLOCK_SIZE (1024 * 16) -#endif - -#ifndef GC_MAX_ALLOC_SIZE -#define GC_MAX_ALLOC_SIZE (GC_BLOCK_SIZE - 16) -#endif - -#ifndef GC_ALLOC_BLOCK -#define GC_ALLOC_BLOCK xmalloc -#endif - -#ifdef PXT64 -#define HIGH_SHIFT 48 -#define BYTES_TO_WORDS(x) ((x) >> 3) -#define WORDS_TO_BYTES(x) ((x) << 3) -#define ALIGN_TO_WORD(x) (((x) + 7) & (~7ULL)) -#define VAR_BLOCK_WORDS(vt) ((uint32_t)(vt) >> 2) -#else -#define HIGH_SHIFT 28 -#define BYTES_TO_WORDS(x) ((x) >> 2) -#define WORDS_TO_BYTES(x) ((x) << 2) -#define ALIGN_TO_WORD(x) (((x) + 3) & (~3U)) -#define VAR_BLOCK_WORDS(vt) (((uint32_t)(vt) << 4) >> (4 + 2)) -#endif - -#define FREE_MASK (1ULL << (HIGH_SHIFT + 3)) -#define ARRAY_MASK (1ULL << (HIGH_SHIFT + 2)) -#define PERMA_MASK (1ULL << (HIGH_SHIFT + 1)) -#define MARKED_MASK 0x1 -#define ANY_MARKED_MASK 0x3 - -// the bit operations should be faster than loading large constants -#define IS_FREE(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 3)) -#define IS_ARRAY(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 2)) & 1) -#define IS_PERMA(vt) (((uintptr_t)(vt) >> (HIGH_SHIFT + 1)) & 1) -#define IS_VAR_BLOCK(vt) ((uintptr_t)(vt) >> (HIGH_SHIFT + 2)) -#define IS_MARKED(vt) ((uintptr_t)(vt)&MARKED_MASK) -#define IS_LIVE(vt) (IS_MARKED(vt) || (((uintptr_t)(vt) >> (HIGH_SHIFT)) == 0x6)) - -//#define PXT_GC_DEBUG 1 -#ifndef PXT_GC_CHECKS -#define PXT_GC_CHECKS 1 -#endif -//#define PXT_GC_STRESS 1 - -//#define PXT_GC_CHECKS 1 - -#define MARK(v) \ - do { \ - GC_CHECK(inGCArea(v), 42); \ - *(uintptr_t *)(v) |= MARKED_MASK; \ - } while (0) - -#ifdef PXT_GC_DEBUG -#define LOG DMESG -#define VLOG DMESG -#define VVLOG DMESG -#else -#define LOG NOLOG -#define VLOG NOLOG -#define VVLOG NOLOG -#endif - -#ifdef PXT_GC_CHECKS -#define GC_CHECK(cond, code) \ - if (!(cond)) \ - oops(code) -#else -#define GC_CHECK(cond, code) ((void)0) -#endif - -namespace pxt { - -// keep in sync with base/control.ts, function gcStats() -struct GCStats { - uint32_t numGC; - uint32_t numBlocks; - uint32_t totalBytes; - uint32_t lastFreeBytes; - uint32_t lastMaxBlockBytes; - uint32_t minFreeBytes; -}; - -static GCStats gcStats; - -//% expose -Buffer getGCStats() { - return mkBuffer((uint8_t *)&gcStats, sizeof(gcStats)); -} - -//% -void popThreadContext(ThreadContext *ctx); -//% -ThreadContext *pushThreadContext(void *sp, void *endSP); - -unsigned RefRecord_gcsize(RefRecord *r) { - VTable *tbl = getVTable(r); - return BYTES_TO_WORDS(tbl->numbytes); -} - -#ifdef PXT_GC_THREAD_LIST -ThreadContext *threadContexts; -#endif - -#define IN_GC_ALLOC 1 -#define IN_GC_COLLECT 2 -#define IN_GC_FREEZE 4 -#define IN_GC_PREALLOC 8 - -#ifndef PXT_VM -static TValue *tempRoot; -static uint8_t tempRootLen; -#endif - -uint8_t inGC; - -void popThreadContext(ThreadContext *ctx) { -#ifndef PXT_VM - VLOG("pop: %p", ctx); - - if (!ctx) - return; - - auto n = ctx->stack.next; - if (n) { - VLOG("seg %p", n); - ctx->stack.top = n->top; - ctx->stack.bottom = n->bottom; - ctx->stack.next = n->next; - app_free(n); - } else { -#ifdef PXT_GC_THREAD_LIST - if (ctx->next) - ctx->next->prev = ctx->prev; - if (ctx->prev) - ctx->prev->next = ctx->next; - else { - if (threadContexts != ctx) - oops(41); - threadContexts = ctx->next; - if (threadContexts) - threadContexts->prev = NULL; - } -#endif - app_free(ctx); - setThreadContext(NULL); - } -#endif -} - -#define ALLOC(tp) (tp *)app_alloc(sizeof(tp)) - -ThreadContext *pushThreadContext(void *sp, void *endSP) { -#ifdef PXT_VM - return NULL; -#else - if (PXT_IN_ISR()) - target_panic(PANIC_CALLED_FROM_ISR); - - auto curr = getThreadContext(); - tempRoot = (TValue *)endSP; - tempRootLen = (uintptr_t *)sp - (uintptr_t *)endSP; - if (curr) { -#ifdef PXT_GC_THREAD_LIST -#ifdef PXT_GC_DEBUG - auto ok = false; - for (auto p = threadContexts; p; p = p->next) - if (p == curr) { - ok = true; - break; - } - if (!ok) - oops(49); -#endif -#endif - auto seg = ALLOC(StackSegment); - VLOG("stack %p / %p", seg, curr); - seg->top = curr->stack.top; - seg->bottom = curr->stack.bottom; - seg->next = curr->stack.next; - curr->stack.next = seg; - } else { - curr = ALLOC(ThreadContext); - LOG("push: %p", curr); - curr->globals = globals; - curr->stack.next = NULL; - curr->thrownValue = TAG_NON_VALUE; - curr->tryFrame = NULL; - -#ifdef PXT_GC_THREAD_LIST - curr->next = threadContexts; - curr->prev = NULL; - if (curr->next) - curr->next->prev = curr; - threadContexts = curr; -#endif - setThreadContext(curr); - } - tempRootLen = 0; - curr->stack.bottom = sp; - curr->stack.top = NULL; - return curr; -#endif -} - -class RefBlock : public RefObject { - public: - RefBlock *nextFree; -}; - -struct GCBlock { - GCBlock *next; - uint32_t blockSize; - RefObject data[0]; -}; - -struct PendingArray { - PendingArray *next; - TValue *data; - unsigned len; -}; - -#define PENDING_ARRAY_THR 100 - -static PendingArray *pendingArrays; -static LLSegment gcRoots; -LLSegment workQueue; // (ab)used by consString making -static GCBlock *firstBlock; -static RefBlock *firstFree; -static uint8_t *midPtr; - -static bool inGCArea(void *ptr) { - for (auto block = firstBlock; block; block = block->next) { - if ((void *)block->data <= ptr && ptr < (void *)((uint8_t *)block->data + block->blockSize)) - return true; - } - return false; -} - -#define NO_MAGIC(vt) ((VTable *)vt)->magic != VTABLE_MAGIC -#define VT(p) (*(uintptr_t *)(p)) -#define SKIP_PROCESSING(p) \ - (isReadOnly(p) || (VT(p) & (ANY_MARKED_MASK | ARRAY_MASK)) || NO_MAGIC(VT(p))) - -void gcMarkArray(void *data) { - auto segBl = (uintptr_t *)data - 1; - GC_CHECK(!IS_MARKED(VT(segBl)), 47); - MARK(segBl); -} - -void gcScan(TValue v) { - if (SKIP_PROCESSING(v)) - return; - MARK(v); - workQueue.push(v); -} - -void gcScanMany(TValue *data, unsigned len) { - // VLOG("scan: %p %d", data, len); - for (unsigned i = 0; i < len; ++i) { - auto v = data[i]; - // VLOG("psh: %p %d %d", v, isReadOnly(v), (*(uint32_t *)v & 1)); - if (SKIP_PROCESSING(v)) - continue; - MARK(v); - workQueue.push(v); - if (workQueue.getLength() > PENDING_ARRAY_THR) { - i++; - // store rest of the work for later, when we have cleared the queue - auto pa = (PendingArray *)xmalloc(sizeof(PendingArray)); - pa->next = pendingArrays; - pa->data = data + i; - pa->len = len - i; - pendingArrays = pa; - break; - } - } -} - -void gcScanSegment(Segment &seg) { - auto data = seg.getData(); - if (!data) - return; - VVLOG("seg %p %d", data, seg.getLength()); - gcMarkArray(data); - gcScanMany(data, seg.getLength()); -} - -#define getScanMethod(vt) ((RefObjectMethod)(((VTable *)(vt))->methods[2])) -#define getSizeMethod(vt) ((RefObjectSizeMethod)(((VTable *)(vt))->methods[3])) - -void gcProcess(TValue v) { - if (SKIP_PROCESSING(v)) - return; - VVLOG("gcProcess: %p", v); - MARK(v); - auto scan = getScanMethod(VT(v) & ~ANY_MARKED_MASK); - if (scan) - scan((RefObject *)v); - for (;;) { - while (workQueue.getLength()) { - auto curr = (RefObject *)workQueue.pop(); - VVLOG(" - %p", curr); - scan = getScanMethod(curr->vt() & ~ANY_MARKED_MASK); - if (scan) - scan(curr); - } - if (pendingArrays) { - auto pa = pendingArrays; - pendingArrays = pa->next; - auto data = pa->data; - auto len = pa->len; - xfree(pa); - gcScanMany(data, len); - } else { - break; - } - } -} - -static void mark(int flags) { -#ifdef PXT_GC_DEBUG - flags |= 2; -#endif - auto data = gcRoots.getData(); - auto len = gcRoots.getLength(); - if (flags & 2) { - DMESG("--MARK"); - DMESG("RP:%p/%d", data, len); - } - for (unsigned i = 0; i < len; ++i) { - auto d = data[i]; - if ((uintptr_t)d & 1) { - d = *(TValue *)((uintptr_t)d & ~1); - } - gcProcess(d); - } - -#ifdef PXT_GC_THREAD_LIST - for (auto ctx = threadContexts; ctx; ctx = ctx->next) { - gcProcess(ctx->thrownValue); - for (auto seg = &ctx->stack; seg; seg = seg->next) { - auto ptr = (TValue *)threadAddressFor(ctx, seg->top); - auto end = (TValue *)threadAddressFor(ctx, seg->bottom); - VLOG("mark: %p - %p", ptr, end); - while (ptr < end) { - gcProcess(*ptr++); - } - } - } -#else - gcProcessStacks(flags); -#endif - - if (globals) { -#ifdef PXT_VM - auto nonPtrs = vmImg->infoHeader->nonPointerGlobals; -#else - auto nonPtrs = bytecode[21]; -#endif - len = getNumGlobals() - nonPtrs; - data = globals + nonPtrs; - if (flags & 2) - DMESG("RG:%p/%d", data, len); - VLOG("globals: %p %d", data, len); - for (unsigned i = 0; i < len; ++i) { - gcProcess(*data++); - } - } - -#ifndef PXT_VM - data = tempRoot; - len = tempRootLen; - for (unsigned i = 0; i < len; ++i) { - gcProcess(*data++); - } -#endif -} - -static uint32_t getObjectSize(RefObject *o) { - auto vt = o->vt() & ~ANY_MARKED_MASK; - uint32_t r; - GC_CHECK(vt != 0, 49); - if (IS_VAR_BLOCK(vt)) { - r = VAR_BLOCK_WORDS(vt); - } else { - auto sz = getSizeMethod(vt); - // GC_CHECK(0x2000 <= (intptr_t)sz && (intptr_t)sz <= 0x100000, 47); - r = sz(o); - } - GC_CHECK(1 <= r && (r <= BYTES_TO_WORDS(GC_MAX_ALLOC_SIZE) || IS_FREE(vt)), 41); - return r; -} - -static void setupFreeBlock(GCBlock *curr) { - gcStats.numBlocks++; - gcStats.totalBytes += curr->blockSize; - curr->data[0].setVT(FREE_MASK | (TOWORDS(curr->blockSize) << 2)); - ((RefBlock *)curr->data)[0].nextFree = firstFree; - firstFree = (RefBlock *)curr->data; - midPtr = (uint8_t *)curr->data + curr->blockSize / 4; -} - -static void linkFreeBlock(GCBlock *curr) { - // blocks need to be sorted by address for midPtr to work - if (!firstBlock || curr < firstBlock) { - curr->next = firstBlock; - firstBlock = curr; - } else { - for (auto p = firstBlock; p; p = p->next) { - if (!p->next || curr < p->next) { - curr->next = p->next; - p->next = curr; - break; - } - } - } -} - -void gcPreAllocateBlock(uint32_t sz) { - auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz); - curr->blockSize = sz - sizeof(GCBlock); - LOG("GC pre-alloc: %p", curr); - GC_CHECK((curr->blockSize & 3) == 0, 40); - setupFreeBlock(curr); - linkFreeBlock(curr); -} - -static GCBlock *allocateBlockCore() { - int sz = GC_BLOCK_SIZE; - void *dummy = NULL; -#ifdef GC_GET_HEAP_SIZE - if (firstBlock) { -#ifdef GC_STACK_BASE - if (!firstBlock->next) { - int memSize = getConfig(CFG_RAM_BYTES, 0); - int codalEnd = GC_STACK_BASE; - // round up to 1k - there is sometimes a few bytes below the stack - codalEnd = (codalEnd + 1024) & ~1023; - int codalSize = codalEnd & 0xffffff; - sz = memSize - codalSize - 4; - if (sz > 0) { - auto curr = (GCBlock *)codalEnd; - curr->blockSize = sz - sizeof(GCBlock); - return curr; - } - } -#endif - gc(2); // dump roots - target_panic(PANIC_GC_OOM); - } - auto lowMem = getConfig(CFG_LOW_MEM_SIMULATION_KB, 0); - auto sysHeapSize = getConfig(CFG_SYSTEM_HEAP_BYTES, 4 * 1024); - auto heapSize = GC_GET_HEAP_SIZE(); - sz = heapSize - sysHeapSize; - if (lowMem) { - auto memIncrement = 32 * 1024; - // get the memory size - assume it's increment of 32k, - // and we don't statically allocate more than 32k - auto memSize = ((heapSize + memIncrement - 1) / memIncrement) * memIncrement; - int fillerSize = memSize - lowMem * 1024; - if (fillerSize > 0) { - dummy = GC_ALLOC_BLOCK(fillerSize); - sz -= fillerSize; - } - } -#endif - auto curr = (GCBlock *)GC_ALLOC_BLOCK(sz); - curr->blockSize = sz - sizeof(GCBlock); - // make sure reference to allocated block is stored somewhere, otherwise - // GCC optimizes out the call to GC_ALLOC_BLOCK - curr->data[4].setVT((uintptr_t)dummy); - return curr; -} - -__attribute__((noinline)) static void allocateBlock() { - auto curr = allocateBlockCore(); - DMESG("GC block %db @ %p", curr->blockSize, curr); - GC_CHECK((curr->blockSize & 3) == 0, 40); - setupFreeBlock(curr); - linkFreeBlock(curr); -} - -static void sweep(int flags) { - RefBlock *prevFreePtr = NULL; - uint32_t freeSize = 0; - uint32_t totalSize = 0; - uint32_t maxFreeBlock = 0; - firstFree = NULL; - - gcStats.numGC++; - - for (auto h = firstBlock; h; h = h->next) { - auto d = h->data; - auto words = BYTES_TO_WORDS(h->blockSize); - auto end = d + words; - totalSize += words; - VLOG("sweep: %p - %p", d, end); - while (d < end) { - if (IS_LIVE(d->vtable)) { - VVLOG("Live %p", d); - d->setVT(d->vt() & ~MARKED_MASK); - d += getObjectSize(d); - } else { - auto start = (RefBlock *)d; - while (d < end) { - if (IS_FREE(d->vtable)) { - VVLOG("Free %p", d); - } else if (IS_LIVE(d->vtable)) { - break; - } else if (IS_ARRAY(d->vtable)) { - VVLOG("Dead Arr %p", d); - } else { - VVLOG("Dead Obj %p", d); - GC_CHECK(d->vtable->magic == VTABLE_MAGIC, 41); - d->destroyVT(); - VVLOG("destroyed"); - } - d += getObjectSize(d); - } - auto sz = d - (RefObject *)start; - freeSize += sz; - if (sz > (int)maxFreeBlock) - maxFreeBlock = sz; -#ifdef PXT_GC_CHECKS - memset((void *)start, 0xff, WORDS_TO_BYTES(sz)); -#endif - start->setVT((sz << 2) | FREE_MASK); - if (sz > 1) { - start->nextFree = NULL; - if (!prevFreePtr) { - firstFree = start; - } else { - prevFreePtr->nextFree = start; - } - prevFreePtr = start; - } - } - } - } - - if (midPtr) { - uint32_t currFree = 0; - auto limit = freeSize * 1 / 2; - for (auto p = firstFree; p; p = p->nextFree) { - auto len = VAR_BLOCK_WORDS(p->vtable); - currFree += len; - if (currFree > limit) { - midPtr = (uint8_t *)p + ((limit - currFree + len) << 2); - break; - } - } - } - - freeSize = WORDS_TO_BYTES(freeSize); - totalSize = WORDS_TO_BYTES(totalSize); - maxFreeBlock = WORDS_TO_BYTES(maxFreeBlock); - - gcStats.lastFreeBytes = freeSize; - gcStats.lastMaxBlockBytes = maxFreeBlock; - - if (gcStats.minFreeBytes == 0 || gcStats.minFreeBytes > freeSize) - gcStats.minFreeBytes = freeSize; - - if (flags & 1) - DMESG("GC %d/%d free; %d maxBlock", freeSize, totalSize, maxFreeBlock); - else - LOG("GC %d/%d free; %d maxBlock", freeSize, totalSize, maxFreeBlock); - -#ifndef GC_GET_HEAP_SIZE - // if the heap is 90% full, allocate a new block - if (freeSize * 10 <= totalSize) { - allocateBlock(); - } -#endif -} - -void gc(int flags) { - startPerfCounter(PerfCounters::GC); - GC_CHECK(!(inGC & IN_GC_COLLECT), 40); - inGC |= IN_GC_COLLECT; - VLOG("GC mark"); - mark(flags); - VLOG("GC sweep"); - sweep(flags); - VLOG("GC done"); - stopPerfCounter(PerfCounters::GC); - inGC &= ~IN_GC_COLLECT; -} - -#ifdef GC_GET_HEAP_SIZE -extern "C" void free(void *ptr) { - if (!ptr) - return; - if (inGCArea(ptr)) - app_free(ptr); - else - xfree(ptr); -} - -extern "C" void *malloc(size_t sz) { - if (PXT_IN_ISR() || inGC) - return xmalloc(sz); - else - return app_alloc(sz); -} - -extern "C" void *realloc(void *ptr, size_t size) { - if (inGCArea(ptr)) { - void *mem = malloc(size); - - if (ptr != NULL && mem != NULL) { - auto r = (uintptr_t *)ptr; - GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41); - size_t blockSize = VAR_BLOCK_WORDS(r[-1]); - memcpy(mem, ptr, min(blockSize * sizeof(void *), size)); - free(ptr); - } - - return mem; - } else { - return device_realloc(ptr, size); - } -} -#endif - -void *gcAllocateArray(int numbytes) { - numbytes = ALIGN_TO_WORD(numbytes); - numbytes += sizeof(void *); - auto r = (uintptr_t *)gcAllocate(numbytes); - *r = ARRAY_MASK | (TOWORDS(numbytes) << 2); - return r + 1; -} - -static void *gcAllocAt(void *hint, int numbytes) { - gc(0); - size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes)); - - for (auto p = firstFree; p; p = p->nextFree) { - GC_CHECK(!isReadOnly((TValue)p), 49); - auto vt = p->vtable; - GC_CHECK(IS_FREE(vt), 43); - int offset = BYTES_TO_WORDS((uint8_t *)hint - (uint8_t *)p); - int left = (int)(VAR_BLOCK_WORDS(vt) - numwords - offset); - // we give ourselves some space here, so we don't get some strange overlaps - if (offset >= 8 && left >= 8) { - auto nf = (RefBlock *)((void **)p + numwords + offset); - nf->setVT((left << 2) | FREE_MASK); - nf->nextFree = p->nextFree; - p->nextFree = nf; - p->setVT((offset << 2) | FREE_MASK); - p = (RefBlock *)((void **)p + offset); - p->setVT(0); - return p; - } - } - - return NULL; -} - -void *app_alloc_at(void *at, int numbytes) { - if (numbytes < 8) - return NULL; - if (!at) - return NULL; - - numbytes = ALIGN_TO_WORD(numbytes) + sizeof(void *); - auto r = (uintptr_t *)gcAllocAt((uintptr_t *)at - 1, numbytes); - if (!r) - return NULL; - *r = ARRAY_MASK | PERMA_MASK | (TOWORDS(numbytes) << 2); - gc(0); - return r + 1; -} - -void *app_alloc(int numbytes) { - if (!numbytes) - return NULL; - - // gc(0); - auto r = (uintptr_t *)gcAllocateArray(numbytes); - r[-1] |= PERMA_MASK; - return r; -} - -void *app_free(void *ptr) { - auto r = (uintptr_t *)ptr; - GC_CHECK((r[-1] >> (HIGH_SHIFT + 1)) == 3, 41); - r[-1] |= FREE_MASK; - return r; -} - -void gcFreeze() { - inGC |= IN_GC_FREEZE; -} - -void gcReset() { - inGC &= ~IN_GC_FREEZE; - - gcRoots.setLength(0); - - if (inGC) - oops(41); - - if (workQueue.getLength()) - oops(41); - - memset(&gcStats, 0, sizeof(gcStats)); - firstFree = NULL; - for (auto h = firstBlock; h; h = h->next) { - setupFreeBlock(h); - } -} - -#ifdef PXT_VM -void gcPreStartup() { - inGC |= IN_GC_PREALLOC; -} - -void gcStartup() { - inGC &= ~IN_GC_PREALLOC; -} -#endif - -void *gcAllocate(int numbytes) { - size_t numwords = BYTES_TO_WORDS(ALIGN_TO_WORD(numbytes)); - // VVLOG("alloc %d bytes %d words", numbytes, numwords); - - if (numbytes > GC_MAX_ALLOC_SIZE) - target_panic(PANIC_GC_TOO_BIG_ALLOCATION); - - if (PXT_IN_ISR() || (inGC & (IN_GC_PREALLOC | IN_GC_ALLOC | IN_GC_COLLECT | IN_GC_FREEZE))) - target_panic(PANIC_CALLED_FROM_ISR); - - inGC |= IN_GC_ALLOC; - -#if defined(PXT_GC_CHECKS) && !defined(PXT_VM) - { - auto curr = getThreadContext(); - if (curr && !curr->stack.top) - oops(46); - } -#endif - -#ifdef PXT_GC_STRESS - gc(0); -#endif - - for (int i = 0;; ++i) { - RefBlock *prev = NULL; - for (auto p = firstFree; p; p = p->nextFree) { - VVLOG("p=%p", p); - if (i == 0 && (uint8_t *)p > midPtr) { - VLOG("past midptr %p; gc", midPtr); - break; - } - GC_CHECK(!isReadOnly((TValue)p), 49); - auto vt = p->vtable; - if (!IS_FREE(vt)) - oops(43); - int left = (int)(VAR_BLOCK_WORDS(vt) - numwords); - VVLOG("%p %d - %d = %d", (void *)vt, (int)VAR_BLOCK_WORDS(vt), (int)numwords, left); - if (left >= 0) { - auto nf = (RefBlock *)((void **)p + numwords); - auto nextFree = p->nextFree; // p and nf can overlap when allocating 4 bytes - // VVLOG("nf=%p nef=%p", nf, nextFree); - if (left) - nf->setVT((left << 2) | FREE_MASK); - if (left >= 2) { - nf->nextFree = nextFree; - } else { - nf = nextFree; - } - if (prev) - prev->nextFree = nf; - else - firstFree = nf; - p->setVT(0); - VVLOG("GC=>%p %d %p -> %p,%p", p, numwords, nf, nf ? nf->nextFree : 0, - nf ? (void *)nf->vtable : 0); - GC_CHECK(!nf || !nf->nextFree || !isReadOnly((TValue)nf->nextFree), 48); - inGC &= ~IN_GC_ALLOC; - return p; - } - prev = p; - } - - // we didn't find anything, try GC - if (i == 0) - gc(0); - // GC didn't help, try new block - else if (i == 1) - allocateBlock(); - else - // the block allocated was apparently too small - target_panic(PANIC_GC_OOM); - } -} - -static void removePtr(TValue v) { - int len = gcRoots.getLength(); - auto data = gcRoots.getData(); - // scan from the back, as this is often used as a stack - for (int i = len - 1; i >= 0; --i) { - if (data[i] == v) { - if (i == len - 1) { - gcRoots.pop(); - } else { - data[i] = gcRoots.pop(); - } - return; - } - } - oops(40); -} - -void registerGC(TValue *root, int numwords) { - if (!numwords) - return; - - if (numwords > 1) { - while (numwords-- > 0) { - registerGC(root++, 1); - } - return; - } - - gcRoots.push((TValue)((uintptr_t)root | 1)); -} - -void unregisterGC(TValue *root, int numwords) { - if (!numwords) - return; - if (numwords > 1) { - while (numwords-- > 0) { - unregisterGC(root++, 1); - } - return; - } - - removePtr((TValue)((uintptr_t)root | 1)); -} - -void registerGCPtr(TValue ptr) { - if (isReadOnly(ptr)) - return; - gcRoots.push(ptr); -} - -void unregisterGCPtr(TValue ptr) { - if (isReadOnly(ptr)) - return; - removePtr(ptr); -} - -void RefImage::scan(RefImage *t) { - gcScan((TValue)t->buffer); -} - -void RefCollection::scan(RefCollection *t) { - gcScanSegment(t->head); -} - -void RefAction::scan(RefAction *t) { - gcScanMany(t->fields, t->len); -} - -void RefRefLocal::scan(RefRefLocal *t) { - gcScan(t->v); -} - -void RefMap::scan(RefMap *t) { - gcScanSegment(t->keys); - gcScanSegment(t->values); -} - -void RefRecord_scan(RefRecord *r) { - VTable *tbl = getVTable(r); - gcScanMany(r->fields, BYTES_TO_WORDS(tbl->numbytes - sizeof(RefRecord))); -} - -#define SIZE(off) TOWORDS(sizeof(*t) + (off)) - -unsigned RefImage::gcsize(RefImage *t) { - return SIZE(0); -} - -unsigned RefCollection::gcsize(RefCollection *t) { - return SIZE(0); -} - -unsigned RefAction::gcsize(RefAction *t) { - return SIZE(WORDS_TO_BYTES(t->len)); -} - -unsigned RefRefLocal::gcsize(RefRefLocal *t) { - return SIZE(0); -} - -unsigned RefMap::gcsize(RefMap *t) { - return SIZE(0); -} - -} // namespace pxt diff --git a/libs/base/gcstats.ts b/libs/base/gcstats.ts deleted file mode 100644 index 3dd3a79c..00000000 --- a/libs/base/gcstats.ts +++ /dev/null @@ -1,40 +0,0 @@ -namespace control { - //% shim=pxt::getGCStats - function getGCStats(): Buffer { - return null - } - - export interface GCStats { - numGC: number; - numBlocks: number; - totalBytes: number; - lastFreeBytes: number; - lastMaxBlockBytes: number; - minFreeBytes: number; - } - - /** - * Get various statistics about the garbage collector (GC) - */ - export function gcStats(): GCStats { - const buf = getGCStats() - if (!buf) - return null - let off = 0 - const res: any = {} - - addField("numGC") - addField("numBlocks") - addField("totalBytes") - addField("lastFreeBytes") - addField("lastMaxBlockBytes") - addField("minFreeBytes") - - return res - - function addField(name: string) { - res[name] = buf.getNumber(NumberFormat.UInt32LE, off) - off += 4 - } - } -} \ No newline at end of file diff --git a/libs/base/interval.ts b/libs/base/interval.ts deleted file mode 100644 index 459adef0..00000000 --- a/libs/base/interval.ts +++ /dev/null @@ -1,72 +0,0 @@ -namespace control { - export enum IntervalMode { - Interval, - Timeout, - Immediate - } - - let _intervals: Interval[] = undefined; - class Interval { - - id: number; - func: () => void; - delay: number; - mode: IntervalMode; - - constructor(func: () => void, delay: number, mode: IntervalMode) { - this.id = _intervals.length == 0 - ? 1 : _intervals[_intervals.length - 1].id + 1; - this.func = func; - this.delay = delay; - this.mode = mode; - _intervals.push(this); - - control.runInParallel(() => this.work()); - } - - work() { - // execute - switch (this.mode) { - case IntervalMode.Immediate: - case IntervalMode.Timeout: - if (this.delay > 0) - pause(this.delay); // timeout - if (this.delay >= 0) // immediate, timeout - this.func(); - break; - case IntervalMode.Interval: - while (this.delay > 0) { - pause(this.delay); - // might have been cancelled during this duration - if (this.delay > 0) - this.func(); - } - break; - } - // remove from interval array - _intervals.removeElement(this); - } - - cancel() { - this.delay = -1; - } - } - - export function setInterval(func: () => void, delay: number, mode: IntervalMode): number { - if (!func || delay < 0) return 0; - if (!_intervals) _intervals = []; - const interval = new Interval(func, delay, mode); - return interval.id; - } - - export function clearInterval(intervalId: number, mode: IntervalMode): void { - if (!_intervals) return; - for (let i = 0; i < _intervals.length; ++i) { - const it = _intervals[i]; - if (it.id == intervalId && it.mode == mode) { - it.cancel(); - break; - } - } - } -} \ No newline at end of file diff --git a/libs/base/json.ts b/libs/base/json.ts deleted file mode 100644 index 99d51bd7..00000000 --- a/libs/base/json.ts +++ /dev/null @@ -1,322 +0,0 @@ -namespace JSON { - export function parseIntRadix(s: string, base?: number) { - if (base == null || base == 10) { - return parseFloat(s) | 0 - } - - let m = false - let r = 0 - for (let i = 0; i < s.length; ++i) { - let c = s.charCodeAt(i) - if (c == 0x20 || c == 10 || c == 13 || c == 9) - continue - if (r == 0 && !m && c == 0x2d) { - m = true - continue - } - - let v = -1 - if (0x30 <= c && c <= 0x39) - v = c - 0x30 - else { - c |= 0x20 - if (0x61 <= c && c <= 0x7a) - v = c - 0x61 + 10 - } - - if (0 <= v && v < base) { - r *= base - r += v - } else { - return undefined - } - } - - return m ? -r : r - } - - - class Parser { - ptr: number - s: string - errorMsg: string - - error(msg: string) { - if (!this.errorMsg) { - this.errorMsg = msg + " at position " + this.ptr - this.ptr = this.s.length - } - } - - skipWS() { - for (; ;) { - const c = this.nextChar() - if (c == 0x20 || c == 0x0a || c == 0x0d || c == 0x09) { - // OK - } else { - this.ptr-- - return c - } - } - } - - nextChar() { - if (this.ptr < this.s.length) - return this.s.charCodeAt(this.ptr++) - return 0 - } - - doString() { - let r = "" - this.ptr++ - for (; ;) { - const c = this.s.charAt(this.ptr++) - if (c == "\"") - return r - if (c == "\\") { - let q = this.s.charAt(this.ptr++) - if (q == "b") q = "\b" - else if (q == "n") q = "\n" - else if (q == "r") q = "\r" - else if (q == "t") q = "\t" - else if (q == "u") { - q = String.fromCharCode(parseIntRadix(this.s.slice(this.ptr, this.ptr + 4), 16)) - this.ptr += 4 - } - r += q - } else { - r += c - } - } - } - - doArray(): any[] { - const r = [] - this.ptr++ - for (; ;) { - let c = this.skipWS() - if (c == 0x5d) { - this.ptr++ - return r - } - const v = this.value() - if (this.errorMsg) - return null - r.push(v) - c = this.skipWS() - if (c == 0x2c) { - this.ptr++ - continue - } - if (c == 0x5d) - continue - this.error("expecting comma") - } - } - - doObject() { - const r: any = {} - this.ptr++ - for (; ;) { - let c = this.skipWS() - if (c == 0x7d) { - this.ptr++ - return r - } - if (c != 0x22) { - this.error("expecting key") - return r - } - const k = this.doString() - c = this.skipWS() - if (c != 0x3a) { - this.error("expecting colon") - return r - } - this.ptr++ - const v = this.value() - if (this.errorMsg) - return null - r[k] = v - c = this.skipWS() - if (c == 0x2c) { - this.ptr++ - continue - } - if (c == 0x7d) - continue - this.error("expecting comma, got " + String.fromCharCode(c)) - } - } - - doNumber() { - const beg = this.ptr - for (; ;) { - const c = this.nextChar() - if ((0x30 <= c && c <= 0x39) || c == 0x2b || c == 0x2d || c == 0x2e || c == 0x45 || c == 0x65) { - // one more - } else { - this.ptr-- - break - } - } - const ss = this.s.slice(beg, this.ptr) - if (ss.length == 0) { - this.error("expecting number") - return 0 - } - return parseFloat(ss) - } - - checkKw(k: string) { - if (this.s.slice(this.ptr, this.ptr + k.length) == k) { - this.ptr += k.length - return true - } - return false - } - - value() { - if (this.errorMsg) - return null - - const c = this.skipWS() - if (c == 0x7b) - return this.doObject() - else if (c == 0x5b) - return this.doArray() - else if ((0x30 <= c && c <= 0x39) || c == 0x2d) - return this.doNumber() - else if (c == 0x22) - return this.doString() - else if (c == 0x74 && this.checkKw("true")) - return true - else if (c == 0x66 && this.checkKw("false")) - return false - else if (c == 0x6e && this.checkKw("null")) - return null - - this.error("unexpected token") - return null - } - } - - class Stringifier { - currIndent: string - indentStep: string - indent: number - - doString(s: string) { - let r = "\"" - for (let i = 0; i < s.length; ++i) { - let c = s[i] - if (c == "\n") c = "\\n" - else if (c == "\r") c = "\\r" - else if (c == "\t") c = "\\t" - else if (c == "\b") c = "\\b" - else if (c == "\\") c = "\\\\" - else if (c == "\"") c = "\\\"" - r += c - } - return r + "\"" - } - - go(v: any) { - const t = typeof v - if (t == "string") - return this.doString(v) - else if (t == "boolean" || t == "number" || v == null) - return "" + v - else if (Array.isArray(v)) { - const arr = v as any[] - if (arr.length == 0) - return "[]" - else { - let r = "[" - if (this.indent) { - this.currIndent += this.indentStep - r += "\n" - } - for (let i = 0; i < arr.length; ++i) { - r += this.currIndent + this.go(arr[i]) - if (i != arr.length - 1) - r += "," - if (this.indent) - r += "\n" - } - if (this.indent) - this.currIndent = this.currIndent.slice(this.indent) - r += this.currIndent + "]" - return r - } - } else { - const keys = Object.keys(v) - if (keys.length == 0) - return "{}" - - let r = "{" - if (this.indent) { - this.currIndent += this.indentStep - r += "\n" - } - for (let i = 0; i < keys.length; ++i) { - const k = keys[i] - r += this.currIndent + this.doString(k) - if (this.indent) - r += ": " - else - r += ":" - r += this.go(v[k]) - if (i != keys.length - 1) - r += "," - if (this.indent) - r += "\n" - } - if (this.indent) - this.currIndent = this.currIndent.slice(this.indent) - r += this.currIndent + "}" - return r - } - } - } - - /** - * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. - * @param value A JavaScript value, usually an object or array, to be converted. - * @param replacer Not supported; use null. - * @param indent Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. - */ - export function stringify(value: any, replacer: any = null, indent: number = 0) { - const ss = new Stringifier() - ss.currIndent = "" - indent |= 0 - if (indent < 0) indent = 0 - if (indent > 10) indent = 10 - ss.indentStep = "" - ss.currIndent = "" - ss.indent = indent - while (indent-- > 0) - ss.indentStep += " " - return ss.go(value) - } - - - /** - * Converts a JavaScript Object Notation (JSON) string into an object. - * @param text A valid JSON string. - */ - export function parse(s: string) { - const p = new Parser() - p.ptr = 0 - p.s = s - const r = p.value() - if (p.skipWS()) { - p.error("excessive input") - } - if (p.errorMsg) { - control.dmesg("Invalid JSON: " + p.errorMsg) - return undefined - } - return r - } -} diff --git a/libs/base/loops.cpp b/libs/base/loops.cpp deleted file mode 100644 index 47306ba2..00000000 --- a/libs/base/loops.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "pxtbase.h" - -namespace loops { - -/** - * Repeats the code forever in the background. On each iteration, allows other codes to run. - * @param body code to execute - */ -//% help=loops/forever weight=100 afterOnStart=true deprecated=true -//% blockId=forever_deprecated block="forever" blockAllowMultiple=1 -void forever(Action a) { - runForever(a); -} - -/** - * Pause for the specified time in milliseconds - * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000 - */ -//% help=loops/pause weight=99 deprecated=true -//% async block="pause %pause=timePicker|ms" -//% blockId=device_pause_deprecated -void pause(int ms) { - if (ms < 0) return; - sleep_ms(ms); -} - -} \ No newline at end of file diff --git a/libs/base/math.ts b/libs/base/math.ts deleted file mode 100644 index deafef0e..00000000 --- a/libs/base/math.ts +++ /dev/null @@ -1,83 +0,0 @@ -namespace Math { - - export const E = 2.718281828459045; - export const LN2 = 0.6931471805599453; - export const LN10 = 2.302585092994046; - export const LOG2E = 1.4426950408889634; - export const LOG10E = 0.4342944819032518; - export const PI = 3.141592653589793; - export const SQRT1_2 = 0.7071067811865476; - export const SQRT2 = 1.4142135623730951; - - /** - * Re-maps a number from one range to another. That is, a value of ``from low`` would get mapped to ``to low``, a value of ``from high`` to ``to high``, values in-between to values in-between, etc. - * @param value value to map in ranges - * @param fromLow the lower bound of the value's current range - * @param fromHigh the upper bound of the value's current range, eg: 1023 - * @param toLow the lower bound of the value's target range - * @param toHigh the upper bound of the value's target range, eg: 4 - */ - //% help=math/map weight=10 blockGap=8 - //% blockId=math_map block="map %value|from low %fromLow|high %fromHigh|to low %toLow|high %toHigh" - //% inlineInputMode=inline - export function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number { - return ((value - fromLow) * (toHigh - toLow)) / (fromHigh - fromLow) + toLow; - } - - /** - * Constrains a number to be within a range - * @param x the number to constrain, all data types - * @param y the lower end of the range, all data types - * @param z the upper end of the range, all data types - */ - //% help=math/constrain weight=11 blockGap=8 - //% blockId="math_constrain_value" block="constrain %value|between %low|and %high" - export function constrain(value: number, low: number, high: number): number { - return value < low ? low : value > high ? high : value; - } - - const b_m16: number[] = [0, 49, 49, 41, 90, 27, 117, 10] - /** - * Returns the sine of an input angle. This is an 8-bit approximation. - * @param theta input angle from 0-255 - */ - //% help=math/isin weight=11 advanced=true blockGap=8 - export function isin(theta: number) { - //reference: based on FASTLed's sin approximation method: [https://github.com/FastLED/FastLED](MIT) - let offset = theta; - if( theta & 0x40 ) { - offset = 255 - offset; - } - offset &= 0x3F; // 0..63 - - let secoffset = offset & 0x0F; // 0..15 - if( theta & 0x40) secoffset++; - - let section = offset >> 4; // 0..3 - let s2 = section * 2; - - let b = b_m16[s2]; - let m16 = b_m16[s2+1]; - let mx = (m16 * secoffset) >> 4; - - let y = mx + b; - if( theta & 0x80 ) y = -y; - - y += 128; - - return y; - } - - /** - * Returns the cosine of an input angle. This is an 8-bit approximation. - * @param theta input angle from 0-255 - */ - //% help=math/icos weight=10 advanced=true blockGap=8 - export function icos(theta: number) { - return isin(theta + 16384); - } -} - -namespace Number { - export const EPSILON = 2.220446049250313e-16; -} \ No newline at end of file diff --git a/libs/base/ns.ts b/libs/base/ns.ts deleted file mode 100644 index e478a275..00000000 --- a/libs/base/ns.ts +++ /dev/null @@ -1,7 +0,0 @@ - -/** - * Respond to and read data from buttons and sensors. - */ -//% color="#B4009E" weight=98 icon="\uf192" -namespace input { -} diff --git a/libs/base/pause.ts b/libs/base/pause.ts deleted file mode 100644 index 60df5afd..00000000 --- a/libs/base/pause.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Pause for the specified time in milliseconds - * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000 - */ -//% help=loops/pause weight=99 -//% async block="pause %pause=timePicker|ms" -//% blockId=device_pause blockNamespace="loops" -function pause(ms: number): void { - loops.pause(ms); -} - -// micro:bit compatibility -// these functions allow some level of reuse -// between micro:bit and other maker-style editors -namespace basic { - export function pause(millis: number) { - loops.pause(millis); - } -} \ No newline at end of file diff --git a/libs/base/perfcounters.ts b/libs/base/perfcounters.ts deleted file mode 100644 index d16779f4..00000000 --- a/libs/base/perfcounters.ts +++ /dev/null @@ -1,13 +0,0 @@ -namespace control { - /** - * Enable profiling for current function. - */ - //% shim=TD_NOOP shimArgument=perfCounter - export function enablePerfCounter(name?: string) { } - - /** - * Dump values of profiling performance counters. - */ - //% shim=pxt::dumpPerfCounters - export function dmesgPerfCounters() { } -} diff --git a/libs/base/poll.ts b/libs/base/poll.ts deleted file mode 100644 index 47c8e5ab..00000000 --- a/libs/base/poll.ts +++ /dev/null @@ -1,78 +0,0 @@ -namespace control { - class PollEvent { - public eid: number; - public vid: number; - public start: number; - public timeOut: number; - public condition: () => boolean; - public once: boolean; - constructor(eid: number, vid: number, start: number, timeOut: number, condition: () => boolean, once: boolean) { - this.eid = eid; - this.vid = vid; - this.start = start; - this.timeOut = timeOut; - this.condition = condition; - this.once = once; - } - } - - let _pollEventQueue: PollEvent[] = undefined; - - function pollEvents() { - while (_pollEventQueue.length > 0) { - const now = control.millis(); - for (let i = 0; i < _pollEventQueue.length; ++i) { - const ev = _pollEventQueue[i]; - if (ev.condition() || (ev.timeOut > 0 && now - ev.start > ev.timeOut)) { - control.raiseEvent(ev.eid, ev.vid); - if (ev.once) { - _pollEventQueue.splice(i, 1); - --i; - } - } - } - pause(50); - } - // release fiber - _pollEventQueue = undefined; - } - - export function __queuePollEvent(timeOut: number, condition: () => boolean, handler: () => void) { - const ev = new PollEvent( - control.allocateNotifyEvent(), - 1, - control.millis(), - timeOut, - condition, - !handler - ); - - // start polling fiber if needed - if (!_pollEventQueue) { - _pollEventQueue = [ev]; - control.runInParallel(pollEvents); - } - else { - // add to the queue - _pollEventQueue.push(ev) - } - - // register event - if (handler) - control.onEvent(ev.eid, ev.vid, handler); - else // or wait - control.waitForEvent(ev.eid, ev.vid); - } -} - -/** - * Busy wait for a condition to be true - * @param condition condition to test for - * @param timeOut if positive, maximum duration to wait for in milliseconds - */ -//% blockId="pxt_pause_until" -function pauseUntil(condition: () => boolean, timeOut?: number): void { - if (!condition || condition()) return; // optimistic path - if (!timeOut) timeOut = 0; - control.__queuePollEvent(timeOut, condition, undefined); -} diff --git a/libs/base/pxt.cpp b/libs/base/pxt.cpp deleted file mode 100644 index 747a00a5..00000000 --- a/libs/base/pxt.cpp +++ /dev/null @@ -1,518 +0,0 @@ -#include "pxtbase.h" - -using namespace std; - -namespace pxt { - -Action mkAction(int totallen, RefAction *act) { - check(getVTable(act)->classNo == BuiltInType::RefAction, PANIC_INVALID_BINARY_HEADER, 1); -#ifdef PXT_VM - check(act->initialLen <= totallen, PANIC_INVALID_BINARY_HEADER, 13); -#endif - - if (totallen == 0) { - return (TValue)act; // no closure needed - } - - void *ptr = gcAllocate(sizeof(RefAction) + totallen * sizeof(void *)); - RefAction *r = new (ptr) RefAction(); - r->len = totallen; -#ifdef PXT_VM - r->numArgs = act->numArgs; - r->initialLen = act->initialLen; - r->flags = 0; -#endif - r->func = act->func; - memset(r->fields, 0, r->len * sizeof(void *)); - - MEMDBG("mkAction: start=%p => %p", act, r); - - return (Action)r; -} - -RefRecord *mkClassInstance(VTable *vtable) { - intcheck(vtable->methods[0] == &RefRecord_destroy, PANIC_SIZE, 3); - // intcheck(vtable->methods[1] == &RefRecord_print, PANIC_SIZE, 4); - - void *ptr = gcAllocate(vtable->numbytes); - RefRecord *r = new (ptr) RefRecord(vtable); - memset(r->fields, 0, vtable->numbytes - sizeof(RefRecord)); - MEMDBG("mkClass: vt=%p => %p", vtable, r); - return r; -} - -TValue RefRecord::ld(int idx) { - // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 1); - return fields[idx]; -} - -TValue RefRecord::ldref(int idx) { - // DMESG("LD %p len=%d reflen=%d idx=%d", this, len, reflen, idx); - // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 2); - return fields[idx]; -} - -void RefRecord::st(int idx, TValue v) { - // intcheck((reflen == 255 ? 0 : reflen) <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 3); - fields[idx] = v; -} - -void RefRecord::stref(int idx, TValue v) { - // DMESG("ST %p len=%d reflen=%d idx=%d", this, len, reflen, idx); - // intcheck(0 <= idx && idx < reflen, PANIC_OUT_OF_BOUNDS, 4); - fields[idx] = v; -} - -void RefObject::destroyVT() { - ((RefObjectMethod)getVTable(this)->methods[0])(this); -} - -//% -void deleteRefObject(RefObject *obj) { - obj->destroyVT(); -} - -void RefObject::printVT() { - ((RefObjectMethod)getVTable(this)->methods[1])(this); -} - -void RefRecord_destroy(RefRecord *) {} - -void RefRecord_print(RefRecord *r) { - DMESG("RefRecord %p size=%d bytes", r, getVTable(r)->numbytes); -} - -void Segment::set(unsigned i, TValue value) { - if (i < size) { - data[i] = value; - } else if (i < Segment::MaxSize) { - growByMin(i + 1); - data[i] = value; - } else { - return; - } - if (length <= i) { - length = i + 1; - } - -#ifdef DEBUG_BUILD - DMESG("In Segment::set"); - this->print(); -#endif - - return; -} - -static inline int growthFactor(int size) { - if (size == 0) { - return 4; - } - if (size < 64) { - return size * 2; // Double - } - if (size < 512) { - return size * 5 / 3; // Grow by 1.66 rate - } - // Grow by constant rate - if ((unsigned)size + 256 < Segment::MaxSize) - return size + 256; - else - return Segment::MaxSize; -} - -void LLSegment::setLength(unsigned newLen) { - if (newLen > Segment::MaxSize) - return; - - if (newLen > size) { - int newSize = growthFactor(size); - if (newSize < (int)newLen) - newSize = newLen; - - // this will throw if unable to allocate - TValue *tmp = (TValue *)(xmalloc(newSize * sizeof(TValue))); - - // Copy existing data - if (size) { - memcpy(tmp, data, size * sizeof(TValue)); - } - // fill the rest with default value - memset(tmp + size, 0, (newSize - size) * sizeof(TValue)); - - // free older segment; - xfree(data); - - data = tmp; - size = newSize; - } else if (newLen < length) { - memset(data + newLen, 0, (length - newLen) * sizeof(TValue)); - } - - length = newLen; -} - -void LLSegment::set(unsigned idx, TValue v) { - if (idx >= Segment::MaxSize) - return; - if (idx >= length) - setLength(idx + 1); - data[idx] = v; -} - -TValue LLSegment::pop() { - if (length > 0) { - --length; - TValue value = data[length]; - data[length] = 0; - return value; - } - return 0; -} - -void LLSegment::destroy() { - length = size = 0; - xfree(data); - data = nullptr; -} - -void Segment::growByMin(ramint_t minSize) { - ramint_t newSize = max(minSize, (ramint_t)growthFactor(size)); - - if (size < newSize) { - // this will throw if unable to allocate - TValue *tmp = (TValue *)(gcAllocateArray(newSize * sizeof(TValue))); - - // Copy existing data - if (size) - memcpy(tmp, data, size * sizeof(TValue)); - // fill the rest with default value - memset(tmp + size, 0, (newSize - size) * sizeof(TValue)); - - data = tmp; - size = newSize; - -#ifdef DEBUG_BUILD - DMESG("growBy - after reallocation"); - this->print(); -#endif - } - // else { no shrinking yet; } - return; -} - -void Segment::ensure(ramint_t newSize) { - if (newSize < size) { - return; - } - growByMin(newSize); -} - -void Segment::setLength(unsigned newLength) { - if (newLength > size) { - ensure(newLength); - } - length = newLength; - return; -} - -TValue Segment::pop() { -#ifdef DEBUG_BUILD - DMESG("In Segment::pop"); - this->print(); -#endif - - if (length > 0) { - --length; - TValue value = data[length]; - data[length] = Segment::DefaultValue; - return value; - } - return Segment::DefaultValue; -} - -// this function removes an element at index i and shifts the rest of the elements to -// left to fill the gap -TValue Segment::remove(unsigned i) { -#ifdef DEBUG_BUILD - DMESG("In Segment::remove index:%d", i); - this->print(); -#endif - if (i < length) { - // value to return - TValue ret = data[i]; - if (i + 1 < length) { - // Move the rest of the elements to fill in the gap. - memmove(data + i, data + i + 1, (length - i - 1) * sizeof(void *)); - } - length--; - data[length] = Segment::DefaultValue; -#ifdef DEBUG_BUILD - DMESG("After Segment::remove index:%d", i); - this->print(); -#endif - return ret; - } - return Segment::DefaultValue; -} - -// this function inserts element value at index i by shifting the rest of the elements right. -void Segment::insert(unsigned i, TValue value) { -#ifdef DEBUG_BUILD - DMESG("In Segment::insert index:%d value:%d", i, value); - this->print(); -#endif - - if (i < length) { - ensure(length + 1); - - // Move the rest of the elements to fill in the gap. - memmove(data + i + 1, data + i, (length - i) * sizeof(void *)); - - data[i] = value; - length++; - } else { - // This is insert beyond the length, just call set which will adjust the length - set(i, value); - } -#ifdef DEBUG_BUILD - DMESG("After Segment::insert index:%d", i); - this->print(); -#endif -} - -void Segment::print() { - DMESG("Segment: %p, length: %d, size: %d", data, (unsigned)length, (unsigned)size); - for (unsigned i = 0; i < size; i++) { - DMESG("-> %d", (unsigned)(uintptr_t)data[i]); - } -} - -void Segment::destroy() { -#ifdef DEBUG_BUILD - DMESG("In Segment::destroy"); - this->print(); -#endif - length = size = 0; - data = nullptr; -} - -PXT_VTABLE_CTOR(RefCollection) {} - -void RefCollection::destroy(RefCollection *t) { - t->head.destroy(); -} - -void RefCollection::print(RefCollection *t) { - DMESG("RefCollection %p size=%d", t, t->head.getLength()); - t->head.print(); -} - -PXT_VTABLE(RefAction, ValType::Function) -RefAction::RefAction() : PXT_VTABLE_INIT(RefAction) {} - -// fields[] contain captured locals -void RefAction::destroy(RefAction *t) {} - -void RefAction::print(RefAction *t) { -#ifdef PXT_VM - DMESG("RefAction %p pc=%X size=%d", t, (uint32_t)t->func, t->len); -#else - DMESG("RefAction %p pc=%X size=%d", t, (const uint8_t *)t->func - (const uint8_t *)bytecode, - t->len); -#endif -} - -PXT_VTABLE_CTOR(RefRefLocal) { - v = 0; -} - -void RefRefLocal::print(RefRefLocal *t) { - DMESG("RefRefLocal %p v=%p", t, (void *)t->v); -} - -void RefRefLocal::destroy(RefRefLocal *t) { - decr(t->v); -} - -PXT_VTABLE_CTOR(RefMap) {} - -void RefMap::destroy(RefMap *t) { - t->keys.destroy(); - t->values.destroy(); -} - -int RefMap::findIdx(String key) { - auto len = keys.getLength(); - auto data = (String *)keys.getData(); - - // fast path - for (unsigned i = 0; i < len; ++i) { - if (data[i] == key) - return i; - } - - // slow path - auto keylen = key->getUTF8Size(); - auto keydata = key->getUTF8Data(); - for (unsigned i = 0; i < len; ++i) { - auto s = data[i]; - if (s->getUTF8Size() == keylen && memcmp(keydata, s->getUTF8Data(), keylen) == 0) - return i; - } - - return -1; -} - -void RefMap::print(RefMap *t) { - DMESG("RefMap %p size=%d", t, t->keys.getLength()); -} - -void debugMemLeaks() {} - -void error(PXT_PANIC code, int subcode) { - DMESG("Error: %d [%d]", code, subcode); - target_panic(code); -} - -#ifndef PXT_VM -uint16_t *bytecode; -#endif -TValue *globals; - -void checkStr(bool cond, const char *msg) { - if (!cond) { - while (true) { - // uBit.display.scroll(msg, 100); - // uBit.sleep(100); - } - } -} - -#ifdef PXT_VM -int templateHash() { - return (int)vmImg->infoHeader->hexHash; -} - -int programHash() { - return (int)vmImg->infoHeader->programHash; -} - -int getNumGlobals() { - return (int)vmImg->infoHeader->allocGlobals; -} - -String programName() { - return mkString((char *)vmImg->infoHeader->name); -} -#else -int templateHash() { - return ((int *)bytecode)[4]; -} - -int programHash() { - return ((int *)bytecode)[6]; -} - -int getNumGlobals() { - return bytecode[16]; -} - -String programName() { - return ((String *)bytecode)[15]; -} -#endif - -#ifndef PXT_VM -void variantNotSupported(const char *v) { - DMESG("variant not supported: %s", v); - target_panic(PANIC_VARIANT_NOT_SUPPORTED); -} - -void exec_binary(unsigned *pc) { - // XXX re-enable once the calibration code is fixed and [editor/embedded.ts] - // properly prepends a call to [internal_main]. - // ::touch_develop::internal_main(); - - // unique group for radio based on source hash - // ::touch_develop::micro_bit::radioDefaultGroup = programHash(); - - unsigned ver = *pc++; - checkStr(ver == 0x4210, ":( Bad runtime version"); - - bytecode = *((uint16_t **)pc++); // the actual bytecode is here - - if (((uint32_t *)bytecode)[0] == 0x923B8E71) { - variantNotSupported((const char *)bytecode + 16); - return; - } - - globals = (TValue *)app_alloc(sizeof(TValue) * getNumGlobals()); - memset(globals, 0, sizeof(TValue) * getNumGlobals()); - - // can be any valid address, best in RAM for speed - globals[0] = (TValue)&globals; - - // just compare the first word - // TODO - checkStr(((uint32_t *)bytecode)[0] == 0x923B8E70 && (unsigned)templateHash() == *pc, - ":( Failed partial flash"); - - uintptr_t startptr = (uintptr_t)bytecode; - - startptr += 64; // header - - initPerfCounters(); - - initRuntime(); - - runAction0((Action)startptr); - - pxt::releaseFiber(); -} - -void start() { - exec_binary((unsigned *)functionsAndBytecode); -} -#endif - -} // namespace pxt - -namespace Array_ { -//% -bool isArray(TValue arr) { - auto vt = getAnyVTable(arr); - return vt && vt->classNo == BuiltInType::RefCollection; -} -} // namespace Array_ - -namespace pxtrt { -//% expose -RefCollection *keysOf(TValue v) { - auto r = NEW_GC(RefCollection); - MEMDBG("mkColl[keys]: => %p", r); - if (getAnyVTable(v) != &RefMap_vtable) - return r; - auto rm = (RefMap *)v; - auto len = rm->keys.getLength(); - if (!len) - return r; - registerGCObj(r); - r->setLength(len); - auto dst = r->getData(); - memcpy(dst, rm->keys.getData(), len * sizeof(TValue)); - unregisterGCObj(r); - return r; -} -//% expose -TValue mapDeleteByString(RefMap *map, String key) { - if (getAnyVTable((TValue)map) != &RefMap_vtable) - target_panic(PANIC_DELETE_ON_CLASS); - int i = map->findIdx(key); - if (i >= 0) { - map->keys.remove(i); - map->values.remove(i); - } - return TAG_TRUE; -} - -} // namespace pxtrt diff --git a/libs/base/pxt.json b/libs/base/pxt.json index 5757ad06..14eb6de7 100644 --- a/libs/base/pxt.json +++ b/libs/base/pxt.json @@ -1,59 +1,3 @@ { - "name": "base", - "description": "The base library", - "files": [ - "README.md", - "pxt-core.d.ts", - "pxt.cpp", - "gc.cpp", - "configkeys.h", - "pxtbase.h", - "core.cpp", - "advmath.cpp", - "trig.cpp", - "pxt-helpers.ts", - "fixed.ts", - "buffer.cpp", - "buffer.ts", - "shims.d.ts", - "enums.d.ts", - "loops.cpp", - "math.ts", - "ns.ts", - "control.cpp", - "controlgc.cpp", - "control.ts", - "interval.ts", - "gcstats.ts", - "poll.ts", - "console.ts", - "json.ts", - "templates.ts", - "eventcontext.ts", - "pause.ts", - "forever.ts", - "utfdecoder.ts", - "scheduling.ts", - "controlmessage.ts", - "perfcounters.ts" - ], - "testFiles": [ - "test.ts" - ], - "public": true, - "partial": true, - "dependencies": {}, - "yotta": { - "optionalConfig": { - "PXT_GC_CHECKS": 0 - }, - "userConfigs": [ - { - "description": "(Diagnostics) Garbage Collection checks.", - "config": { - "PXT_GC_CHECKS": 1 - } - } - ] - } -} \ No newline at end of file + "additionalFilePath": "../../node_modules/pxt-common-packages/libs/base" +} diff --git a/libs/base/pxtbase.h b/libs/base/pxtbase.h deleted file mode 100644 index 60883c6e..00000000 --- a/libs/base/pxtbase.h +++ /dev/null @@ -1,1220 +0,0 @@ -#ifndef __PXTBASE_H -#define __PXTBASE_H - -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wformat" -#pragma GCC diagnostic ignored "-Warray-bounds" - -// needed for gcc6; not sure why -#undef min -#undef max - -#define NOLOG(...) \ - do { \ - } while (0) - -#define MEMDBG NOLOG -//#define MEMDBG DMESG -#define MEMDBG2 NOLOG - -#include "pxtconfig.h" -#include "configkeys.h" -#include "TeknikioDevice.h" - -#ifndef PXT_UTF8 -#define PXT_UTF8 0 -#endif - -#if defined(PXT_VM) -#include -#if UINTPTR_MAX == 0xffffffff -#define PXT32 1 -#elif UINTPTR_MAX == 0xffffffffffffffff -#define PXT64 1 -#else -#error "UINTPTR_MAX has invalid value" -#endif -#endif - -#define intcheck(...) check(__VA_ARGS__) -//#define intcheck(...) do {} while (0) - -#ifdef PXT_USE_FLOAT -#define NUMBER float -#else -#define NUMBER double -#endif - -#include -#include -#include - -#ifdef POKY -void *operator new(size_t size, void *ptr); -void *operator new(size_t size); -#else -#include -#endif - -#include "platform.h" -#include "pxtcore.h" - -#ifndef PXT_REGISTER_RESET -#define PXT_REGISTER_RESET(fn) ((void)0) -#endif - -#define PXT_REFCNT_FLASH 0xfffe - -#define CONCAT_1(a, b) a##b -#define CONCAT_0(a, b) CONCAT_1(a, b) -// already provided in some platforms, like mbedos -#ifndef STATIC_ASSERT -#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }; -#endif - -#ifndef ramint_t -// this type limits size of arrays -#if defined(__linux__) || defined(PXT_VM) -// TODO fix the inline array accesses to take note of this! -#define ramint_t uint32_t -#else -#define ramint_t uint16_t -#endif -#endif - -#ifndef PXT_IN_ISR -#define PXT_IN_ISR() (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) -#endif - -#ifdef POKY -inline void *operator new(size_t, void *p) { - return p; -} -inline void *operator new[](size_t, void *p) { - return p; -} -#endif - -namespace pxt { - -void initTeknikio(); - -}; - -namespace pxt { - -template inline const T &max(const T &a, const T &b) { - if (a < b) - return b; - return a; -} - -template inline const T &min(const T &a, const T &b) { - if (a < b) - return a; - return b; -} - -template inline void swap(T &a, T &b) { - T tmp = a; - a = b; - b = tmp; -} - -// -// Tagged values (assume 4 bytes for now, Cortex-M0) -// -struct TValueStruct {}; -typedef TValueStruct *TValue; - -typedef TValue TNumber; -typedef TValue Action; -typedef TValue ImageLiteral; - -// To be implemented by the target -extern "C" void target_panic(int error_code); -extern "C" void target_reset(); -void sleep_ms(unsigned ms); -void sleep_us(uint64_t us); -void releaseFiber(); -uint64_t current_time_us(); -int current_time_ms(); -void initRuntime(); -void initSystemTimer(); -void sendSerial(const char *data, int len); -void setSendToUART(void (*f)(const char *, int)); -uint64_t getLongSerialNumber(); -void registerWithDal(int id, int event, Action a, int flags = 16); // EVENT_LISTENER_DEFAULT_FLAGS -void runInParallel(Action a); -void runForever(Action a); -void waitForEvent(int id, int event); -//% -unsigned afterProgramPage(); -//% -void dumpDmesg(); -uint32_t hash_fnv1(const void *data, unsigned len); - -// also defined DMESG macro -// end - -#define TAGGED_SPECIAL(n) (TValue)(void *)((n << 2) | 2) -#define TAG_FALSE TAGGED_SPECIAL(2) // 10 -#define TAG_TRUE TAGGED_SPECIAL(16) // 66 -#define TAG_UNDEFINED (TValue)0 -#define TAG_NULL TAGGED_SPECIAL(1) // 6 -#define TAG_NAN TAGGED_SPECIAL(3) // 14 -#define TAG_NUMBER(n) (TNumber)(void *)(((uintptr_t)(uint32_t)(n) << 1) | 1) -#define TAG_NON_VALUE TAGGED_SPECIAL(4) // 18; doesn't represent any JS value - -#ifdef PXT_VM -inline bool isEncodedDouble(uint64_t v) { - return (v >> 48) != 0; -} -#endif - -inline bool isDouble(TValue v) { -#ifdef PXT64 - return ((uintptr_t)v >> 48) != 0; -#else - (void)v; - return false; -#endif -} - -inline bool isPointer(TValue v) { - return !isDouble(v) && v != 0 && ((intptr_t)v & 3) == 0; -} - -inline bool isTagged(TValue v) { - return (!isDouble(v) && ((intptr_t)v & 3)) || !v; -} - -inline bool isInt(TValue v) { - return !isDouble(v) && ((intptr_t)v & 1); -} - -inline bool isSpecial(TValue v) { - return !isDouble(v) && ((intptr_t)v & 2); -} - -inline bool bothNumbers(TValue a, TValue b) { - return !isDouble(a) && !isDouble(b) && ((intptr_t)a & (intptr_t)b & 1); -} - -inline int numValue(TValue n) { - return (int)((intptr_t)n >> 1); -} - -inline bool canBeTagged(int v) { - (void)v; -#ifdef PXT_BOX_DEBUG - return false; -#elif defined(PXT64) - return true; -#else - return (v << 1) >> 1 == v; -#endif -} - -// see https://anniecherkaev.com/the-secret-life-of-nan - -#define NanBoxingOffset 0x1000000000000LL - -template TO bitwise_cast(FROM in) { - STATIC_ASSERT(sizeof(TO) == sizeof(FROM)); - union { - FROM from; - TO to; - } u; - u.from = in; - return u.to; -} - -inline double decodeDouble(uint64_t v) { - return bitwise_cast(v - NanBoxingOffset); -} - -#ifdef PXT64 -STATIC_ASSERT(sizeof(void *) == 8); -inline double doubleVal(TValue v) { - return bitwise_cast((uint64_t)v - NanBoxingOffset); -} - -inline TValue tvalueFromDouble(double d) { - return (TValue)(bitwise_cast(d) + NanBoxingOffset); -} -#else -STATIC_ASSERT(sizeof(void *) == 4); -#endif - -// keep in sym with sim/control.ts -typedef enum { - PANIC_CODAL_OOM = 20, - PANIC_GC_OOM = 21, - PANIC_GC_TOO_BIG_ALLOCATION = 22, - PANIC_CODAL_HEAP_ERROR = 30, - PANIC_CODAL_NULL_DEREFERENCE = 40, - PANIC_CODAL_USB_ERROR = 50, - PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR = 90, - - PANIC_INVALID_BINARY_HEADER = 901, - PANIC_OUT_OF_BOUNDS = 902, - PANIC_REF_DELETED = 903, - PANIC_SIZE = 904, - PANIC_INVALID_VTABLE = 905, - PANIC_INTERNAL_ERROR = 906, - PANIC_NO_SUCH_CONFIG = 907, - PANIC_NO_SUCH_PIN = 908, - PANIC_INVALID_ARGUMENT = 909, - PANIC_MEMORY_LIMIT_EXCEEDED = 910, - PANIC_SCREEN_ERROR = 911, - PANIC_MISSING_PROPERTY = 912, - PANIC_INVALID_IMAGE = 913, - PANIC_CALLED_FROM_ISR = 914, - PANIC_HEAP_DUMPED = 915, - PANIC_STACK_OVERFLOW = 916, - PANIC_BLOCKING_TO_STRING = 917, - PANIC_VM_ERROR = 918, - PANIC_SETTINGS_CLEARED = 920, - PANIC_SETTINGS_OVERLOAD = 921, - PANIC_SETTINGS_SECRET_MISSING = 922, - PANIC_DELETE_ON_CLASS = 923, - PANIC_OUT_OF_TIMERS = 924, - PANIC_JACDAC = 925, - PANIC_MICROPHONE_MISSING = 926, - PANIC_VARIANT_NOT_SUPPORTED = 927, - - PANIC_CAST_FIRST = 980, - PANIC_CAST_FROM_UNDEFINED = 980, - PANIC_CAST_FROM_BOOLEAN = 981, - PANIC_CAST_FROM_NUMBER = 982, - PANIC_CAST_FROM_STRING = 983, - PANIC_CAST_FROM_OBJECT = 984, - PANIC_CAST_FROM_FUNCTION = 985, - PANIC_CAST_FROM_NULL = 989, - - PANIC_UNHANDLED_EXCEPTION = 999, - -} PXT_PANIC; - -extern const uintptr_t functionsAndBytecode[]; -extern TValue *globals; -extern uint16_t *bytecode; -class RefRecord; - -// Utility functions - -typedef TValue (*RunActionType)(Action a, TValue arg0, TValue arg1, TValue arg2); - -#define asmRunAction3 ((RunActionType)(((uintptr_t *)bytecode)[12])) - -static inline TValue runAction3(Action a, TValue arg0, TValue arg1, TValue arg2) { - return asmRunAction3(a, arg0, arg1, 0); -} -static inline TValue runAction2(Action a, TValue arg0, TValue arg1) { - return asmRunAction3(a, arg0, arg1, 0); -} -static inline TValue runAction1(Action a, TValue arg0) { - return asmRunAction3(a, arg0, 0, 0); -} -static inline TValue runAction0(Action a) { - return asmRunAction3(a, 0, 0, 0); -} - -class RefAction; -class BoxedString; -struct VTable; - -//% -Action mkAction(int totallen, RefAction *act); -//% expose -int templateHash(); -//% expose -int programHash(); -//% expose -BoxedString *programName(); -//% expose -unsigned programSize(); -//% -int getNumGlobals(); -//% -RefRecord *mkClassInstance(VTable *vt); -//% -void debugMemLeaks(); -//% -void anyPrint(TValue v); - -//% -int getConfig(int key, int defl = -1); - -//% -int toInt(TNumber v); -//% -unsigned toUInt(TNumber v); -//% -NUMBER toDouble(TNumber v); -//% -float toFloat(TNumber v); -//% -TNumber fromDouble(NUMBER r); -//% -TNumber fromFloat(float r); - -//% -TNumber fromInt(int v); -//% -TNumber fromUInt(unsigned v); -//% -TValue fromBool(bool v); -//% -bool eq_bool(TValue a, TValue b); -//% -bool eqq_bool(TValue a, TValue b); - -//% -void failedCast(TValue v, void *addr = NULL); -//% -void missingProperty(TValue v); - -void error(PXT_PANIC code, int subcode = 0); -void exec_binary(unsigned *pc); -void start(); - -struct HandlerBinding { - HandlerBinding *next; - int source; - int value; - Action action; -}; -HandlerBinding *findBinding(int source, int value); -HandlerBinding *nextBinding(HandlerBinding *curr, int source, int value); -void setBinding(int source, int value, Action act); - -// Legacy stuff; should no longer be used -//% -TValue incr(TValue e); -//% -void decr(TValue e); - -inline TValue incr(TValue e) { - return e; -} -inline void decr(TValue e) {} - -class RefObject; - -static inline RefObject *incrRC(RefObject *r) { - return r; -} -static inline void decrRC(RefObject *) {} - -inline void *ptrOfLiteral(int offset) { - return &bytecode[offset]; -} - -// Checks if object is ref-counted, and has a custom PXT vtable in front -// TODO -inline bool isRefCounted(TValue e) { - return isPointer(e); -} - -inline void check(int cond, PXT_PANIC code, int subcode = 0) { - if (!cond) - error(code, subcode); -} - -inline void oops(int subcode = 0) { - target_panic(800 + subcode); -} - -class RefObject; - -typedef void (*RefObjectMethod)(RefObject *self); -typedef unsigned (*RefObjectSizeMethod)(RefObject *self); -typedef void *PVoid; -typedef void **PPVoid; - -typedef void *Object_; - -#define VTABLE_MAGIC 0xF9 - -enum class ValType : uint8_t { - Undefined, - Boolean, - Number, - String, - Object, - Function, -}; - -// keep in sync with pxt-core (search for the type name) -enum class BuiltInType : uint16_t { - BoxedString = 1, - BoxedNumber = 2, - BoxedBuffer = 3, - RefAction = 4, - RefImage = 5, - RefCollection = 6, - RefRefLocal = 7, - RefMap = 8, - RefMImage = 9, // microbit-specific - MMap = 10, // linux, mostly ev3 - BoxedString_SkipList = 11, // used by VM bytecode representation only - BoxedString_ASCII = 12, // ditto - User0 = 16, -}; - -struct VTable { - uint16_t numbytes; - ValType objectType; - uint8_t magic; -#ifdef PXT_VM - uint16_t ifaceHashEntries; - BuiltInType lastClassNo; -#else - PVoid *ifaceTable; -#endif - BuiltInType classNo; - uint16_t reserved; - uint32_t ifaceHashMult; - - // we only use the first few methods here; pxt will generate more - PVoid methods[8]; -}; - -//% -extern const VTable string_inline_ascii_vt; -#if PXT_UTF8 -//% -extern const VTable string_inline_utf8_vt; -//% -extern const VTable string_cons_vt; -//% -extern const VTable string_skiplist16_vt; -//% -extern const VTable string_skiplist16_packed_vt; -#endif -//% -extern const VTable buffer_vt; -//% -extern const VTable number_vt; -//% -extern const VTable RefAction_vtable; - -#ifndef PXT_IS_READONLY -// assume ARM - ram addresses are 0x2000_0000+; flash is either 0x0+ or 0x0800_0000+ -#define PXT_IS_READONLY(v) (isTagged(v) || !((uintptr_t)v >> 28)) -#endif - -inline bool isReadOnly(TValue v) { - return PXT_IS_READONLY(v); -} - -// A base abstract class for ref-counted objects. -class RefObject { - public: - const VTable *vtable; - - RefObject(const VTable *vt) { -#if defined(PXT32) && defined(PXT_VM) && !defined(PXT_ESP32) - if ((uint32_t)vt & 0xf0000000) - target_panic(PANIC_INVALID_VTABLE); -#endif - vtable = vt; - } - - void destroyVT(); - void printVT(); - - inline uintptr_t vt() { return (uintptr_t)vtable; } - inline void setVT(uintptr_t v) { vtable = (const VTable *)v; } - - inline void ref() {} - inline void unref() {} - inline bool isReadOnly() { return pxt::isReadOnly((TValue)this); } -}; - -class Segment { - private: - TValue *data; - ramint_t length; - ramint_t size; - - // this just gives max value of ramint_t - void growByMin(ramint_t minSize); - void ensure(ramint_t newSize); - - public: - static constexpr ramint_t MaxSize = (((1U << (8 * sizeof(ramint_t) - 1)) - 1) << 1) + 1; - static constexpr TValue DefaultValue = TAG_UNDEFINED; // == NULL - - Segment() : data(nullptr), length(0), size(0) {} - - TValue get(unsigned i) { return i < length ? data[i] : NULL; } - void set(unsigned i, TValue value); - - unsigned getLength() { return length; }; - void setLength(unsigned newLength); - - void push(TValue value) { set(length, value); } - TValue pop(); - - TValue remove(unsigned i); - void insert(unsigned i, TValue value); - - void destroy(); - - void print(); - - TValue *getData() { return data; } -}; - -// Low-Level segment using system malloc -class LLSegment { - private: - TValue *data; - ramint_t length; - ramint_t size; - - public: - LLSegment() : data(nullptr), length(0), size(0) {} - - void set(unsigned idx, TValue v); - void push(TValue value) { set(length, value); } - TValue pop(); - void destroy(); - void setLength(unsigned newLen); - - TValue get(unsigned i) { return i < length ? data[i] : NULL; } - unsigned getLength() { return length; }; - TValue *getData() { return data; } -}; - -// A ref-counted collection of either primitive or ref-counted objects (String, Image, -// user-defined record, another collection) -class RefCollection : public RefObject { - public: - Segment head; - - RefCollection(); - - static void destroy(RefCollection *coll); - static void scan(RefCollection *coll); - static unsigned gcsize(RefCollection *coll); - static void print(RefCollection *coll); - - unsigned length() { return head.getLength(); } - void setLength(unsigned newLength) { head.setLength(newLength); } - TValue getAt(int i) { return head.get(i); } - TValue *getData() { return head.getData(); } -}; - -class RefMap : public RefObject { - public: - Segment keys; - Segment values; - - RefMap(); - static void destroy(RefMap *map); - static void scan(RefMap *map); - static unsigned gcsize(RefMap *coll); - static void print(RefMap *map); - int findIdx(BoxedString *key); -}; - -// A ref-counted, user-defined JS object. -class RefRecord : public RefObject { - public: - // The object is allocated, so that there is space at the end for the fields. - TValue fields[]; - - RefRecord(VTable *v) : RefObject(v) {} - - TValue ld(int idx); - TValue ldref(int idx); - void st(int idx, TValue v); - void stref(int idx, TValue v); -}; - -static inline VTable *getVTable(RefObject *r) { - return (VTable *)(r->vt() & ~1); -} - -static inline VTable *getAnyVTable(TValue v) { - if (!isRefCounted(v)) - return NULL; - auto vt = getVTable((RefObject *)v); - if (vt->magic == VTABLE_MAGIC) - return vt; - return NULL; -} - -// these are needed when constructing vtables for user-defined classes -//% -void RefRecord_destroy(RefRecord *r); -//% -void RefRecord_print(RefRecord *r); -//% -void RefRecord_scan(RefRecord *r); -//% -unsigned RefRecord_gcsize(RefRecord *r); - -typedef TValue (*ActionCB)(TValue *captured, TValue arg0, TValue arg1, TValue arg2); - -// Ref-counted function pointer. -class RefAction : public RefObject { - public: - uint16_t len; - uint16_t numArgs; -#ifdef PXT_VM - uint16_t initialLen; - uint16_t flags; - uintptr_t func; -#else - ActionCB func; // The function pointer -#endif - // fields[] contain captured locals - TValue fields[]; - - static void destroy(RefAction *act); - static void scan(RefAction *act); - static unsigned gcsize(RefAction *coll); - static void print(RefAction *act); - - RefAction(); - - inline void stCore(int idx, TValue v) { - // DMESG("ST [%d] = %d ", idx, v); this->print(); - intcheck(0 <= idx && idx < len, PANIC_OUT_OF_BOUNDS, 10); - intcheck(fields[idx] == 0, PANIC_OUT_OF_BOUNDS, 11); // only one assignment permitted - fields[idx] = v; - } -}; - -// These two are used to represent locals written from inside inline functions -class RefRefLocal : public RefObject { - public: - TValue v; - static void destroy(RefRefLocal *l); - static void scan(RefRefLocal *l); - static unsigned gcsize(RefRefLocal *l); - static void print(RefRefLocal *l); - RefRefLocal(); -}; - -typedef int color; - -// note: this is hardcoded in PXT (hexfile.ts) - -class BoxedNumber : public RefObject { - public: - NUMBER num; - BoxedNumber() : RefObject(&number_vt) {} -} __attribute__((packed)); - -class BoxedString : public RefObject { - public: - union { - struct { - uint16_t length; // ==size - char data[0]; - } ascii; -#if PXT_UTF8 - struct { - uint16_t size; - char data[0]; - } utf8; - struct { - BoxedString *left; - BoxedString *right; - } cons; - struct { - uint16_t size; // in bytes - uint16_t length; // in characters - uint16_t *list; - } skip; - struct { - uint16_t size; // in bytes - uint16_t length; // in characters - uint16_t list[0]; - } skip_pack; -#endif - }; - -#if PXT_UTF8 - uintptr_t runMethod(int idx) { - return ((uintptr_t(*)(BoxedString *))vtable->methods[idx])(this); - } - const char *getUTF8Data() { return (const char *)runMethod(4); } - uint32_t getUTF8Size() { return (uint32_t)runMethod(5); } - // in characters - uint32_t getLength() { return (uint32_t)runMethod(6); } - const char *getUTF8DataAt(uint32_t pos) { - auto meth = - ((const char *(*)(BoxedString *, uint32_t))vtable->methods[7]); - return meth(this, pos); - } -#else - const char *getUTF8Data() { return ascii.data; } - uint32_t getUTF8Size() { return ascii.length; } - uint32_t getLength() { return ascii.length; } - const char *getUTF8DataAt(uint32_t pos) { return pos < ascii.length ? ascii.data + pos : NULL; } -#endif - - TNumber charCodeAt(int pos); - - BoxedString(const VTable *vt) : RefObject(vt) {} -}; - -// cross version compatible way of accessing string data -#ifndef PXT_STRING_DATA -#define PXT_STRING_DATA(str) str->getUTF8Data() -#endif - -// cross version compatible way of accessing string length -#ifndef PXT_STRING_DATA_LENGTH -#define PXT_STRING_DATA_LENGTH(str) str->getUTF8Size() -#endif - -class BoxedBuffer : public RefObject { - public: - // data needs to be word-aligned, so we use 32 bits for length - int length; - uint8_t data[0]; - BoxedBuffer() : RefObject(&buffer_vt) {} -}; - -// cross version compatible way of access data field -#ifndef PXT_BUFFER_DATA -#define PXT_BUFFER_DATA(buffer) buffer->data -#endif - -// cross version compatible way of access data length -#ifndef PXT_BUFFER_LENGTH -#define PXT_BUFFER_LENGTH(buffer) buffer->length -#endif - -#ifndef PXT_CREATE_BUFFER -#define PXT_CREATE_BUFFER(data, len) pxt::mkBuffer(data, len) -#endif - -// Legacy format: -// the first byte of data indicates the format - currently 0xE1 or 0xE4 to 1 or 4 bit bitmaps -// second byte indicates width in pixels -// third byte indicates the height (which should also match the size of the buffer) -// just like ordinary buffers, these can be layed out in flash - -// Current format: -// 87 BB WW WW HH HH 00 00 DATA -// that is: 0x87, 0x01 or 0x04 - bpp, width in little endian, height, 0x00, 0x00 followed by data -// for 4 bpp images, rows are word-aligned (as in legacy) - -#define IMAGE_HEADER_MAGIC 0x87 - -struct ImageHeader { - uint8_t magic; - uint8_t bpp; - uint16_t width; - uint16_t height; - uint16_t padding; - uint8_t pixels[0]; -}; - -class RefImage : public RefObject { - public: - BoxedBuffer *buffer; - - RefImage(BoxedBuffer *buf); - RefImage(uint32_t sz); - - void setBuffer(BoxedBuffer *b); - - uint8_t *data() { return buffer->data; } - int length() { return (int)buffer->length; } - - ImageHeader *header() { return (ImageHeader *)buffer->data; } - int pixLength() { return length() - sizeof(ImageHeader); } - - int width() { return header()->width; } - int height() { return header()->height; } - int wordHeight(); - int bpp() { return header()->bpp; } - - bool hasPadding() { return (height() & 0x7) != 0; } - - uint8_t *pix() { return header()->pixels; } - - int byteHeight() { - if (bpp() == 1) - return (height() + 7) >> 3; - else if (bpp() == 4) - return ((height() * 4 + 31) >> 5) << 2; - else { - oops(21); - return -1; - } - } - - uint8_t *pix(int x, int y) { - uint8_t *d = &pix()[byteHeight() * x]; - if (y) { - if (bpp() == 1) - d += y >> 3; - else if (bpp() == 4) - d += y >> 1; - } - return d; - } - - uint8_t fillMask(color c); - bool inRange(int x, int y); - void clamp(int *x, int *y); - void makeWritable(); - - static void destroy(RefImage *t); - static void scan(RefImage *t); - static unsigned gcsize(RefImage *t); - static void print(RefImage *t); -}; - -RefImage *mkImage(int w, int h, int bpp); - -typedef BoxedBuffer *Buffer; -typedef BoxedString *String; -typedef RefImage *Image_; - -uint32_t toRealUTF8(String str, uint8_t *dst); - -// keep in sync with github/pxt/pxtsim/libgeneric.ts -enum class NumberFormat { - Int8LE = 1, - UInt8LE, - Int16LE, - UInt16LE, - Int32LE, - Int8BE, - UInt8BE, - Int16BE, - UInt16BE, - Int32BE, - - UInt32LE, - UInt32BE, - Float32LE, - Float64LE, - Float32BE, - Float64BE, -}; - -// this will, unlike mkStringCore, UTF8-canonicalize the data -String mkString(const char *data, int len = -1); -// data can be NULL in both cases -Buffer mkBuffer(const void *data, int len); -String mkStringCore(const char *data, int len = -1); - -TNumber getNumberCore(uint8_t *buf, int size, NumberFormat format); -void setNumberCore(uint8_t *buf, int size, NumberFormat format, TNumber value); - -void seedRandom(unsigned seed); -void seedAddRandom(unsigned seed); -// max is inclusive -unsigned getRandom(unsigned max); - -ValType valType(TValue v); - -// this is equivalent to JS `throw v`; it will leave -// the current function(s), all the way until the nearest try block and -// ignore all destructors (think longjmp()) -void throwValue(TValue v); - -void registerGC(TValue *root, int numwords = 1); -void unregisterGC(TValue *root, int numwords = 1); -void registerGCPtr(TValue ptr); -void unregisterGCPtr(TValue ptr); -static inline void registerGCObj(RefObject *ptr) { - registerGCPtr((TValue)ptr); -} -static inline void unregisterGCObj(RefObject *ptr) { - unregisterGCPtr((TValue)ptr); -} -void gc(int flags); - -struct StackSegment { - void *top; - void *bottom; - StackSegment *next; -}; - -#define NUM_TRY_FRAME_REGS 3 -struct TryFrame { - TryFrame *parent; - uintptr_t registers[NUM_TRY_FRAME_REGS]; -}; - -struct ThreadContext { - TValue *globals; - StackSegment stack; - TryFrame *tryFrame; - TValue thrownValue; -#ifdef PXT_GC_THREAD_LIST - ThreadContext *next; - ThreadContext *prev; -#endif -}; - -#ifdef PXT_GC_THREAD_LIST -extern ThreadContext *threadContexts; -void *threadAddressFor(ThreadContext *, void *sp); -#endif - -void releaseThreadContext(ThreadContext *ctx); -ThreadContext *getThreadContext(); -void setThreadContext(ThreadContext *ctx); - -#ifndef PXT_GC_THREAD_LIST -void gcProcessStacks(int flags); -#endif - -void gcProcess(TValue v); -void gcFreeze(); - -#ifdef PXT_VM -void gcStartup(); -void gcPreStartup(); -#endif - -void coreReset(); -void gcReset(); -void systemReset(); - -void *gcAllocate(int numbytes); -void *gcAllocateArray(int numbytes); -extern "C" void *app_alloc(int numbytes); -extern "C" void *app_free(void *ptr); -extern "C" void *app_alloc_at(void *at, int numbytes); -void gcPreAllocateBlock(uint32_t sz); - -int redirectSamples(int16_t *dst, int numsamples, int samplerate); - -#ifdef PXT64 -#define TOWORDS(bytes) (((bytes) + 7) >> 3) -#else -#define TOWORDS(bytes) (((bytes) + 3) >> 2) -#endif - -#ifndef PXT_VM -#define soft_panic target_panic -#endif - -extern int debugFlags; - -enum class PerfCounters { - GC, -}; - -#ifdef PXT_PROFILE -#ifndef PERF_NOW -#error "missing platform timer support" -#endif - -struct PerfCounter { - uint32_t value; - uint32_t numstops; - uint32_t start; -}; - -extern struct PerfCounter *perfCounters; - -void initPerfCounters(); -//% -void dumpPerfCounters(); -//% -void startPerfCounter(PerfCounters n); -//% -void stopPerfCounter(PerfCounters n); -#else -inline void startPerfCounter(PerfCounters n) {} -inline void stopPerfCounter(PerfCounters n) {} -inline void initPerfCounters() {} -inline void dumpPerfCounters() {} -#endif - -// Handling of built-in string literals (like "[Object]", "true" etc.). - -// This has the same layout as BoxedString, but has statically allocated buffer -template struct BoxedStringLayout { - const void *vtable; - uint16_t size; - const char data[N]; -}; - -template constexpr size_t _boxedStringLen(char const (&)[N]) { - return N; -} - -// strings defined here as used as (String)name -#define PXT_DEF_STRING(name, val) \ - const BoxedStringLayout<_boxedStringLen(val)> name[1] = { \ - {&pxt::string_inline_ascii_vt, _boxedStringLen(val) - 1, val}}; - -// bigger value - less memory, but slower -// 16/20 keeps s.length and s.charCodeAt(i) at about 200 cycles (for actual unicode strings), -// which is similar to amortized allocation time -#define PXT_STRING_SKIP_INCR 16 // needs to be power of 2; needs to be kept in sync with compiler -#define PXT_STRING_MIN_SKIP 20 // min. size of string to use skip list; static code has its own limit - -#define PXT_NUM_SKIP_ENTRIES(p) ((p)->skip.length / PXT_STRING_SKIP_INCR) -#define PXT_SKIP_DATA_IND(p) ((const char *)(p->skip.list + PXT_NUM_SKIP_ENTRIES(p))) -#define PXT_SKIP_DATA_PACK(p) ((const char *)(p->skip_pack.list + PXT_NUM_SKIP_ENTRIES(p))) - -} // namespace pxt - -using namespace pxt; - -namespace numops { -//% -String toString(TValue v); -//% -int toBool(TValue v); -//% -int toBoolDecr(TValue v); -} // namespace numops - -namespace pxt { -inline bool toBoolQuick(TValue v) { - if (v == TAG_TRUE) - return true; - if (v == TAG_FALSE || v == TAG_UNDEFINED || v == TAG_NULL) - return false; - return numops::toBool(v); -} -} // namespace pxt - -namespace pxtrt { -//% -RefMap *mkMap(); -//% -TValue mapGetByString(RefMap *map, String key); -//% -int lookupMapKey(String key); -//% -TValue mapGet(RefMap *map, unsigned key); -//% expose -void mapSetByString(RefMap *map, String key, TValue val); -//% -void mapSet(RefMap *map, unsigned key, TValue val); -} // namespace pxtrt - -namespace pins { -Buffer createBuffer(int size); -} - -namespace String_ { -//% -int compare(String a, String b); -} // namespace String_ - -namespace Array_ { -//% -RefCollection *mk(); -//% -int length(RefCollection *c); -//% -void setLength(RefCollection *c, int newLength); -//% -void push(RefCollection *c, TValue x); -//% -TValue pop(RefCollection *c); -//% -TValue getAt(RefCollection *c, int x); -//% -void setAt(RefCollection *c, int x, TValue y); -//% -TValue removeAt(RefCollection *c, int x); -//% -void insertAt(RefCollection *c, int x, TValue value); -//% -int indexOf(RefCollection *c, TValue x, int start); -//% -bool removeElement(RefCollection *c, TValue x); -} // namespace Array_ - -#define NEW_GC(T, ...) new (gcAllocate(sizeof(T))) T(__VA_ARGS__) - -// The ARM Thumb generator in the JavaScript code is parsing -// the hex file and looks for the magic numbers as present here. -// -// Then it fetches function pointer addresses from there. -// -// The vtable pointers are there, so that the ::emptyData for various types -// can be patched with the right vtable. -// -#define PXT_SHIMS_BEGIN \ - namespace pxt { \ - const uintptr_t functionsAndBytecode[] \ - __attribute__((aligned(0x20))) = {0x08010801, 0x42424242, 0x08010801, 0x8de9d83e, - -#define PXT_SHIMS_END \ - } \ - ; \ - } - -#if !defined(X86_64) && !defined(PXT_VM) -#pragma GCC diagnostic ignored "-Wpmf-conversions" -#endif - -#ifdef PXT_VM -#define DEF_VTABLE(name, tp, valtype, ...) \ - const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp, BuiltInType::tp, \ - 0, 0, {__VA_ARGS__}}; -#else -#define DEF_VTABLE(name, tp, valtype, ...) \ - const VTable name = {sizeof(tp), valtype, VTABLE_MAGIC, 0, BuiltInType::tp, \ - 0, 0, {__VA_ARGS__}}; -#endif - -#define PXT_VTABLE(classname, valtp) \ - DEF_VTABLE(classname##_vtable, classname, valtp, (void *)&classname::destroy, \ - (void *)&classname::print, (void *)&classname::scan, (void *)&classname::gcsize) - -#define PXT_VTABLE_INIT(classname) RefObject(&classname##_vtable) - -#define PXT_VTABLE_CTOR(classname) \ - PXT_VTABLE(classname, ValType::Object) \ - classname::classname() : PXT_VTABLE_INIT(classname) - -#define PXT_MAIN \ - int main() { \ - pxt::initTeknikio(); \ - pxt::start(); \ - return 0; \ - } - -#define PXT_FNPTR(x) (uintptr_t)(void *)(x) - -#define PXT_ABI(...) - -#define JOIN(a, b) a##b -/// Defines getClassName() function to fetch the singleton -#define SINGLETON(ClassName) \ - static ClassName *JOIN(inst, ClassName); \ - ClassName *JOIN(get, ClassName)() { \ - if (!JOIN(inst, ClassName)) \ - JOIN(inst, ClassName) = new ClassName(); \ - return JOIN(inst, ClassName); \ - } - -/// Defines getClassName() function to fetch the singleton if PIN present -#define SINGLETON_IF_PIN(ClassName, pin) \ - static ClassName *JOIN(inst, ClassName); \ - ClassName *JOIN(get, ClassName)() { \ - if (!JOIN(inst, ClassName) && LOOKUP_PIN(pin)) \ - JOIN(inst, ClassName) = new ClassName(); \ - return JOIN(inst, ClassName); \ - } - -#ifdef PXT_VM -#include "vm.h" -#endif - -#endif diff --git a/libs/base/scheduling.ts b/libs/base/scheduling.ts deleted file mode 100644 index 93bc1af6..00000000 --- a/libs/base/scheduling.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Calls a function with a fixed time delay between each call to that function. - * @param func - * @param delay - */ -//% -function setInterval(func: () => void, delay: number): number { - delay = Math.max(10, delay | 0); - return control.setInterval(func, delay, control.IntervalMode.Interval); -} - -/** - * Cancels repeated action which was set up using setInterval(). - * @param intervalId - */ -//% -function clearInterval(intervalId: number) { - control.clearInterval(intervalId, control.IntervalMode.Interval); -} - -/** - * Calls a function after specified delay. - * @param func - * @param delay - */ -//% -function setTimeout(func: () => void, delay: number): number { - return control.setInterval(func, delay, control.IntervalMode.Timeout); -} - -/** - * Clears the delay set by setTimeout(). - * @param intervalId - */ -//% -function clearTimeout(intervalId: number) { - control.clearInterval(intervalId, control.IntervalMode.Timeout); -} - -/** - * Calls a function as soon as possible. - * @param func - */ -//% -function setImmediate(func: () => void): number { - return control.setInterval(func, 0, control.IntervalMode.Immediate); -} - -/** - * Cancels the immediate actions. - * @param intervalId - */ -//% -function clearImmediate(intervalId: number) { - control.clearInterval(intervalId, control.IntervalMode.Immediate); -} diff --git a/libs/base/shims.d.ts b/libs/base/shims.d.ts index 6cc66c9e..c765da27 100644 --- a/libs/base/shims.d.ts +++ b/libs/base/shims.d.ts @@ -204,6 +204,8 @@ declare namespace control { */ //% shim=control::dmesgValue function dmesgValue(v: any): void; +} +declare namespace control { /** * Force GC and dump basic information about heap. diff --git a/libs/base/sim/cfg.ts b/libs/base/sim/cfg.ts deleted file mode 100644 index 5c183d65..00000000 --- a/libs/base/sim/cfg.ts +++ /dev/null @@ -1,20 +0,0 @@ -namespace pxsim { - export interface EdgeConnectorBoard { - edgeConnectorState: EdgeConnectorState; - } -} - -namespace pxsim.pxtcore { - export function getPin(id: number): pxsim.Pin { - const b = board() as EdgeConnectorBoard; - if (b && b.edgeConnectorState) - return b.edgeConnectorState.getPin(id); - return undefined; - } - export function lookupPinCfg(key: number): pxsim.Pin { - return getPinCfg(key); - } - export function getPinCfg(key: number): pxsim.Pin { - return getPin(getConfig(key, -1)) - } -} diff --git a/libs/base/sim/control.ts b/libs/base/sim/control.ts deleted file mode 100644 index 2203026e..00000000 --- a/libs/base/sim/control.ts +++ /dev/null @@ -1,220 +0,0 @@ -namespace pxsim.pxtcore { - // TODO: add in support for mode, as in CODAL - export function registerWithDal(id: number, evid: number, handler: RefAction, mode: number = 0) { - board().bus.listen(id, evid, handler); - } - - export function deepSleep() { - // TODO? - console.log("deep sleep requested") - } -} - -namespace pxsim.BufferMethods { - function fnv1(data: Uint8Array) { - let h = 0x811c9dc5 - for (let i = 0; i < data.length; ++i) { - h = (Math as any).imul(h, 0x1000193) ^ data[i] - } - return h - } - - export function hash(buf: RefBuffer, bits: number) { - bits |= 0 - if (bits < 1) - return 0 - const h = fnv1(buf.data) - if (bits >= 32) - return h >>> 0 - else - return ((h ^ (h >>> bits)) & ((1 << bits) - 1)) >>> 0 - } -} - -namespace pxsim.control { - export let runInParallel = thread.runInBackground; - export let delay = thread.pause; - - export function reset() { - pxsim.Runtime.postMessage({ - type: "simulator", - command: "restart", - controlReset: true - }) - const cb = getResume(); - } - export function waitMicros(micros: number) { - thread.pause(micros / 1000); // it prempts not much we can do here. - } - export function deviceName(): string { - let b = board(); - return b && b.id - ? b.id.slice(0, 4) - : "abcd"; - } - export function _ramSize() { - return 32 * 1024 * 1024; - } - export function deviceSerialNumber(): number { - let b = board(); - if (!b) return 42; - let n = 0; - if (b.id) { - n = parseInt(b.id.slice(1)); - if (isNaN(n)) { - n = 0; - for (let i = 0; i < b.id.length; ++i) { - n = ((n << 5) - n) + b.id.charCodeAt(i); - n |= 0; - } - n = Math.abs(n); - } - } - if (!n) n = 42; - return n; - } - export function deviceLongSerialNumber(): RefBuffer { - let b = control.createBuffer(8); - BufferMethods.setNumber(b, BufferMethods.NumberFormat.UInt32LE, 0, deviceSerialNumber()) - return b; - } - export function deviceDalVersion(): string { - return "sim"; - } - export function internalOnEvent(id: number, evid: number, handler: RefAction) { - pxtcore.registerWithDal(id, evid, handler) - } - export function waitForEvent(id: number, evid: number) { - const cb = getResume(); - board().bus.wait(id, evid, cb); - } - - export function allocateNotifyEvent(): number { - let b = board(); - return b.bus.nextNotifyEvent++; - } - - export function raiseEvent(id: number, evid: number, mode: number) { - // TODO mode? - board().bus.queue(id, evid) - } - - export function millis(): number { - return runtime.runningTime(); - } - - export function micros(): number { - return runtime.runningTimeUs() & 0x3fffffff; - } - - export function delayMicroseconds(us: number) { - delay(us / 0.001); - } - - export function createBuffer(size: number) { - return BufferMethods.createBuffer(size) - } - export function dmesg(msg: string) { - console.log(`DMESG: ${msg}`); - } - export function setDebugFlags(flags: number): void { - console.log(`debug flags: ${flags}`); - } - export function heapSnapshot(): void { - console.log(runtime.traceObjects()) - } - - function toStr(v: any) { - if (v instanceof RefRecord) { - return `${v.vtable.name}@${v.id}` - } - - if (v instanceof RefCollection) { - let r = "[" - for (let e of v.toArray()) { - if (r.length > 200) { - r += "..." - break - } - r += toStr(e) + ", " - } - r += "]" - return r - } - - if (typeof v == "function") { - return (v + "").slice(0, 60) + "..." - } - - return v + "" - } - export function dmesgPtr(msg: string, ptr: any) { - console.log(`DMESG: ${msg} ${toStr(ptr)}`); - } - export function dmesgValue(ptr: any) { - console.log(`DMESG: ${toStr(ptr)}`); - } - export function gc() { } - export function profilingEnabled() { - return !!runtime.perfCounters - } - - export function __log(priority: number, str: string) { - let prefix = ""; - switch (priority) { - case 0: prefix = "d>"; break; - case 1: prefix = "l>"; break; - case 2: prefix = "w>"; break; - case 3: prefix = "e>"; break; - } - console.log(prefix + str); - runtime.board.writeSerial(str); - } - - export function heapDump() { - // TODO something better - } - - export function isUSBInitialized() { - return false; - } -} - -// keep in sync with pxtbase.h -namespace pxsim { - export const enum PXT_PANIC { - PANIC_CODAL_OOM = 20, - PANIC_GC_OOM = 21, - PANIC_GC_TOO_BIG_ALLOCATION = 22, - PANIC_CODAL_HEAP_ERROR = 30, - PANIC_CODAL_NULL_DEREFERENCE = 40, - PANIC_CODAL_USB_ERROR = 50, - PANIC_CODAL_HARDWARE_CONFIGURATION_ERROR = 90, - - PANIC_INVALID_BINARY_HEADER = 901, - PANIC_OUT_OF_BOUNDS = 902, - PANIC_REF_DELETED = 903, - PANIC_SIZE = 904, - PANIC_INVALID_VTABLE = 905, - PANIC_INTERNAL_ERROR = 906, - PANIC_NO_SUCH_CONFIG = 907, - PANIC_NO_SUCH_PIN = 908, - PANIC_INVALID_ARGUMENT = 909, - PANIC_MEMORY_LIMIT_EXCEEDED = 910, - PANIC_SCREEN_ERROR = 911, - PANIC_MISSING_PROPERTY = 912, - PANIC_INVALID_IMAGE = 913, - PANIC_CALLED_FROM_ISR = 914, - PANIC_HEAP_DUMPED = 915, - - PANIC_CAST_FIRST = 980, - PANIC_CAST_FROM_UNDEFINED = 980, - PANIC_CAST_FROM_BOOLEAN = 981, - PANIC_CAST_FROM_NUMBER = 982, - PANIC_CAST_FROM_STRING = 983, - PANIC_CAST_FROM_OBJECT = 984, - PANIC_CAST_FROM_FUNCTION = 985, - PANIC_CAST_FROM_NULL = 989, - - } -} \ No newline at end of file diff --git a/libs/base/sim/controlmessage.ts b/libs/base/sim/controlmessage.ts deleted file mode 100644 index 8833f395..00000000 --- a/libs/base/sim/controlmessage.ts +++ /dev/null @@ -1,68 +0,0 @@ - -namespace pxsim.pxtcore { - // general purpose message sending mechanism - export function sendMessage(channel: string, message: RefBuffer, parentOnly?: boolean) { - if (!channel) return; - - Runtime.postMessage({ - type: "messagepacket", - broadcast: !parentOnly, - channel: channel, - data: message && message.data - } as SimulatorControlMessage) - } - - export function peekMessageChannel(): string { - const state = getControlMessageState(); - const msg = state && state.peek(); - return msg && msg.channel; - } - - export function readMessageData(): RefBuffer { - const state = getControlMessageState(); - const msg = state && state.read(); - return msg && new RefBuffer(msg.data); - } -} - -namespace pxsim { - // keep in sync with ts - export const CONTROL_MESSAGE_EVT_ID = 2999; - export const CONTROL_MESSAGE_RECEIVED = 1; - - export class ControlMessageState { - messages: SimulatorControlMessage[]; - enabled: boolean; - - constructor(private board: CommonBoard) { - this.messages = []; - this.enabled = false; - this.board.addMessageListener(msg => this.messageHandler(msg)); - } - private messageHandler(msg: SimulatorMessage) { - if (msg.type == "messagepacket") { - let packet = msg; - this.enqueue(packet); - } - } - enqueue(message: SimulatorControlMessage) { - this.messages.push(message); - this.board.bus.queue(CONTROL_MESSAGE_EVT_ID, CONTROL_MESSAGE_RECEIVED); - } - peek() { - return this.messages[0]; - } - read() { - return this.messages.shift(); - } - } - - - export interface ControlMessageBoard extends CommonBoard { - controlMessageState: ControlMessageState; - } - - export function getControlMessageState() { - return (board() as ControlMessageBoard).controlMessageState; - } -} \ No newline at end of file diff --git a/libs/base/sim/core.ts b/libs/base/sim/core.ts deleted file mode 100644 index 8a59f77d..00000000 --- a/libs/base/sim/core.ts +++ /dev/null @@ -1,14 +0,0 @@ -/// - -namespace pxsim { - export interface CommonBoard extends CoreBoard - , EdgeConnectorBoard, EventBusBoard { - bus: EventBus; - buttonState: CommonButtonState; - edgeConnectorState: EdgeConnectorState; - } - - export function board(): CommonBoard { - return runtime.board as CommonBoard; - } -} \ No newline at end of file diff --git a/libs/base/sim/loops.ts b/libs/base/sim/loops.ts deleted file mode 100644 index 0b82109a..00000000 --- a/libs/base/sim/loops.ts +++ /dev/null @@ -1,4 +0,0 @@ -namespace pxsim.loops { - export let pause = thread.pause; - export let forever = thread.forever; -} \ No newline at end of file diff --git a/libs/base/sim/tsconfig.json b/libs/base/sim/tsconfig.json deleted file mode 100644 index 1db1f5ab..00000000 --- a/libs/base/sim/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "es2017", - "noImplicitAny": true, - "noImplicitReturns": true, - "lib": [ - "DOM", - "DOM.Iterable", - "ES2017" - ], - "rootDir": ".", - "newLine": "LF", - "sourceMap": false - } -} diff --git a/libs/base/templates.ts b/libs/base/templates.ts deleted file mode 100644 index 9c5189b7..00000000 --- a/libs/base/templates.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Tagged hex literal converter - */ -//% shim=@hex -function hex(lits: any, ...args: any[]): Buffer { return null } diff --git a/libs/base/test.ts b/libs/base/test.ts deleted file mode 100644 index db39dde0..00000000 --- a/libs/base/test.ts +++ /dev/null @@ -1,14 +0,0 @@ -let i = 1 -let f = 0.5 -let plus = i + f -let minus = i - f - -let r = Math.random() -let ri = Math.randomRange(5, 10) - - -function check(cond:boolean) { control.assert(cond, 108) } - -check(Buffer.pack("<2h", [0x3412, 0x7856]).toHex() == "12345678") -check(Buffer.pack(">hh", [0x3412, 0x7856]).toHex() == "34127856") -check(Buffer.fromHex("F00d").toHex() == "f00d") \ No newline at end of file diff --git a/libs/base/trig.cpp b/libs/base/trig.cpp deleted file mode 100644 index 7c95e2f0..00000000 --- a/libs/base/trig.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "pxtbase.h" -#include -#include - -using namespace std; - -namespace Math_ { - -#define SINGLE(op) return fromDouble(::op(toDouble(x))); - -//% -TNumber atan2(TNumber y, TNumber x) { - return fromDouble(::atan2(toDouble(y), toDouble(x))); -} - -//% -TNumber tan(TNumber x){SINGLE(tan)} - -//% -TNumber sin(TNumber x){SINGLE(sin)} - -//% -TNumber cos(TNumber x){SINGLE(cos)} - -//% -TNumber atan(TNumber x){SINGLE(atan)} - -//% -TNumber asin(TNumber x){SINGLE(asin)} - -//% -TNumber acos(TNumber x){SINGLE(acos)} - -//% -TNumber sqrt(TNumber x){SINGLE(sqrt)} - -} \ No newline at end of file diff --git a/libs/base/utfdecoder.ts b/libs/base/utfdecoder.ts deleted file mode 100644 index b459f4d0..00000000 --- a/libs/base/utfdecoder.ts +++ /dev/null @@ -1,83 +0,0 @@ -class UTF8Decoder { - private buf: Buffer; - - constructor() { - this.buf = undefined; - } - - add(buf: Buffer) { - if (!buf || !buf.length) return; - - if (!this.buf) - this.buf = buf; - else { - const b = control.createBuffer(this.buf.length + buf.length); - b.write(0, this.buf); - b.write(this.buf.length, buf); - this.buf = b; - } - } - - decodeUntil(delimiter: number): string { - if (!this.buf) return undefined; - delimiter = delimiter | 0; - let i = 0; - for (; i < this.buf.length; ++i) { - const c = this.buf[i]; - // skip multi-chars - if ((c & 0xe0) == 0xc0) - i += 1; - else if ((c & 0xf0) == 0xe0) - i += 2; - else if (c == delimiter) { - // found it - break; - } - } - - if (i >= this.buf.length) - return undefined; - else { - const s = this.buf.slice(0, i).toString(); - if (i + 1 == this.buf.length) - this.buf = undefined; - else - this.buf = this.buf.slice(i + 1); - return s; - } - } - - decode(): string { - if (!this.buf) return ""; - - // scan the end of the buffer for partial characters - let length = 0; - for (let i = this.buf.length - 1; i >= 0; i--) { - const c = this.buf[i]; - if ((c & 0x80) == 0) { - length = i + 1; - break; - } - else if ((c & 0xe0) == 0xc0) { - length = i + 2; - break; - } - else if ((c & 0xf0) == 0xe0) { - length = i + 3; - break; - } - } - // is last beyond the end? - if (length == this.buf.length) { - const s = this.buf.toString(); - this.buf = undefined; - return s; - } else if (length == 0) { // data yet - return ""; - } else { - const s = this.buf.slice(0, length).toString(); - this.buf = this.buf.slice(length); - return s; - } - } -} \ No newline at end of file diff --git a/libs/core---nrf52/led.cpp b/libs/core---nrf52/led.cpp index 6ffc1fa5..d8d8a27f 100644 --- a/libs/core---nrf52/led.cpp +++ b/libs/core---nrf52/led.cpp @@ -13,8 +13,6 @@ namespace pxt { using namespace pxt; - - //% color=#7600A8 weight=101 icon="\uf205" namespace led { From 69b01ca44b2072f0ca7b2f3202d76d36ab8a558e Mon Sep 17 00:00:00 2001 From: JoeBakalor Date: Tue, 20 Jul 2021 12:29:56 -0500 Subject: [PATCH 4/6] pxt updates --- libs/.DS_Store | Bin 14340 -> 12292 bytes .../PxtTeknikio.code-workspace | 148 ------------------ libs/teknikio-bluebird/config.ts | 4 +- libs/teknikio-bluebird/device.d.ts | 2 - libs/teknikio-bluebird/pxt.json | 1 + 5 files changed, 4 insertions(+), 151 deletions(-) delete mode 100644 libs/teknikio-bluebird/PxtTeknikio.code-workspace diff --git a/libs/.DS_Store b/libs/.DS_Store index 2c8104f1cc34ce6266e33ad366c00fc091777aa2..90d6537daa5bf22752d9630ba76dbfa84d43d985 100755 GIT binary patch delta 191 zcmZoEXh~3DU|?W$DortDV9)?EIe-{M3-ADmHUGe&P-Adt;J@xc^Ez0EudwoH>9m4!F|QQ~8r zI6-wXuRx(feiBeU0|P6VWYFLS(yqw%ZM^uNc{0CAAP>-7kZTx#w87*YlZl(>s^&65 JO<@6<0sx+%CUgJ* delta 337 zcmZokXem%&U|?W$DortDU@!nOIe-{M3-ADmHUGsaKuQ!ko)NnL2-BH_*a0vY^_`kQ$aY?f}$ z>-e|y>%E5@QRP$6 Date: Tue, 20 Jul 2021 16:01:28 -0500 Subject: [PATCH 5/6] servo updates --- libs/accelerometer_custom/jacdac.ts | 35 -------------------- libs/accelerometer_custom/pxt.json | 3 +- libs/servo/_locales/servo-jsdoc-strings.json | 14 -------- libs/servo/_locales/servo-strings.json | 15 --------- libs/servo/targetoverrides.ts | 6 ++++ sim/simulator.ts | 1 - 6 files changed, 7 insertions(+), 67 deletions(-) delete mode 100644 libs/accelerometer_custom/jacdac.ts delete mode 100755 libs/servo/_locales/servo-jsdoc-strings.json delete mode 100755 libs/servo/_locales/servo-strings.json create mode 100644 libs/servo/targetoverrides.ts diff --git a/libs/accelerometer_custom/jacdac.ts b/libs/accelerometer_custom/jacdac.ts deleted file mode 100644 index 26ffd847..00000000 --- a/libs/accelerometer_custom/jacdac.ts +++ /dev/null @@ -1,35 +0,0 @@ -namespace jacdac { - export class AccelerometerService extends jacdac.SensorHost { - constructor(name: string) { - super("acc", jacdac.ACCELEROMETER_DEVICE_CLASS); - // TODO: catch all event - input.onGesture(Gesture.Shake, () => this.raiseHostEvent(JDGesture.Shake)); - input.onGesture(Gesture.TiltUp, () => this.raiseHostEvent(JDGesture.TiltUp)); - input.onGesture(Gesture.TiltDown, () => this.raiseHostEvent(JDGesture.TiltDown)); - input.onGesture(Gesture.TiltLeft, () => this.raiseHostEvent(JDGesture.TiltLeft)); - input.onGesture(Gesture.TiltRight, () => this.raiseHostEvent(JDGesture.TiltRight)); - input.onGesture(Gesture.FaceUp, () => this.raiseHostEvent(JDGesture.FaceUp)); - input.onGesture(Gesture.FaceDown, () => this.raiseHostEvent(JDGesture.FaceDown)); - input.onGesture(Gesture.FreeFall, () => this.raiseHostEvent(JDGesture.FreeFall)); - input.onGesture(Gesture.ThreeG, () => this.raiseHostEvent(JDGesture.ThreeG)); - input.onGesture(Gesture.SixG, () => this.raiseHostEvent(JDGesture.SixG)); - input.onGesture(Gesture.EightG, () => this.raiseHostEvent(JDGesture.EightG)); - input.onGesture(Gesture.TwoG, () => this.raiseHostEvent(JDGesture.TwoG)); - } - - raiseCustomGestureEvent(id: number) { - this.raiseHostEvent(JDGesture.TwoG + 1 + (id | 0)); - } - - protected serializeState(): Buffer { - const buf = control.createBuffer(6); - buf.setNumber(NumberFormat.Int16LE, 0, input.acceleration(Dimension.X)); - buf.setNumber(NumberFormat.Int16LE, 2, input.acceleration(Dimension.Y)); - buf.setNumber(NumberFormat.Int16LE, 4, input.acceleration(Dimension.Z)); - return buf; - } - } - - //% fixedInstance whenUsed block="accelerometer service" - export const accelerometerService = new AccelerometerService("acc"); -} \ No newline at end of file diff --git a/libs/accelerometer_custom/pxt.json b/libs/accelerometer_custom/pxt.json index 826e7fa4..ec3543e4 100644 --- a/libs/accelerometer_custom/pxt.json +++ b/libs/accelerometer_custom/pxt.json @@ -19,7 +19,6 @@ ], "public": true, "dependencies": { - "core": "file:../core", - "jacdac": "file:../jacdac" + "core": "file:../core" } } diff --git a/libs/servo/_locales/servo-jsdoc-strings.json b/libs/servo/_locales/servo-jsdoc-strings.json deleted file mode 100755 index fbd92f4a..00000000 --- a/libs/servo/_locales/servo-jsdoc-strings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "servos.Servo.maxAngle": "Gets the maximum angle for the servo", - "servos.Servo.minAngle": "Gets the minimum angle for the servo", - "servos.Servo.run": "Set the throttle on a continuous servo", - "servos.Servo.run|param|speed": "the throttle of the motor from -100% to 100%", - "servos.Servo.setAngle": "Set the servo angle", - "servos.Servo.setPulse": "Set the pulse width to the servo in microseconds", - "servos.Servo.setPulse|param|micros": "the width of the pulse in microseconds", - "servos.Servo.setRange": "Set the possible rotation range angles for the servo between 0 and 180", - "servos.Servo.setRange|param|maxAngle": "the maximum angle from 90 to 180", - "servos.Servo.setRange|param|minAngle": "the minimum angle from 0 to 90", - "servos.Servo.setStopOnNeutral": "Set a servo stop mode so it will stop when the rotation angle is in the neutral position, 90 degrees.", - "servos.Servo.stop": "Stop sending commands to the servo so that its rotation will stop at the current position." -} \ No newline at end of file diff --git a/libs/servo/_locales/servo-strings.json b/libs/servo/_locales/servo-strings.json deleted file mode 100755 index 76839b83..00000000 --- a/libs/servo/_locales/servo-strings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "servos.A1|block": "servo A1", - "servos.A2|block": "servo A2", - "servos.Servo.run|block": "continuous %servo run at %speed=speedPicker \\%", - "servos.Servo.setAngle|block": "set %servo angle to %degrees=protractorPicker °", - "servos.Servo.setPulse|block": "set %servo pulse to %micros μs", - "servos.Servo.setRange|block": "set %servo range from %minAngle to %maxAngle", - "servos.Servo.setStopOnNeutral|block": "set %servo stop on neutral %enabled", - "servos.Servo.stop|block": "stop %servo", - "{id:category}Jacdac": "Jacdac", - "{id:category}Servos": "Servos", - "{id:group}Configuration": "Configuration", - "{id:group}Continuous": "Continuous", - "{id:group}Positional": "Positional" -} \ No newline at end of file diff --git a/libs/servo/targetoverrides.ts b/libs/servo/targetoverrides.ts new file mode 100644 index 00000000..cb457d11 --- /dev/null +++ b/libs/servo/targetoverrides.ts @@ -0,0 +1,6 @@ +namespace servos { + //% block="servo A1" fixedInstance + export const A1 = new servos.PinServo(pins.SERVO_LEFT); + //% block="servo A2" fixedInstance + export const A2 = new servos.PinServo(pins.SERVO_RIGHT); +} \ No newline at end of file diff --git a/sim/simulator.ts b/sim/simulator.ts index 7ce1eb9d..792f2ab4 100755 --- a/sim/simulator.ts +++ b/sim/simulator.ts @@ -165,7 +165,6 @@ namespace pxsim { this.builtinVisuals["screen"] = () => new visuals.ScreenView(); this.builtinPartVisuals["screen"] = (xy: visuals.Coord) => visuals.mkScreenPart(xy); - const neopixelPinCfg = getConfig(DAL.CFG_PIN_NEOPIXEL) || getConfig(DAL.CFG_PIN_DOTSTAR_DATA); if (neopixelPinCfg !== null) From 62156f5d78d8495e6da2f2663f29e37cf37d270c Mon Sep 17 00:00:00 2001 From: JoeBakalor Date: Thu, 12 Aug 2021 16:34:47 -0500 Subject: [PATCH 6/6] remove remaining jacdac --- libs/accelerometer/pxt.json | 29 ++------ libs/accelerometer/shims.d.ts | 8 --- libs/accelerometer_custom/accelhw.cpp | 16 +++-- libs/accelerometer_custom/pxt.json | 3 +- libs/core---nrf52/led.cpp | 8 +-- .../jacdac/_locales/jacdac-jsdoc-strings.json | 41 ----------- libs/jacdac/_locales/jacdac-strings.json | 72 ------------------- libs/jacdac/pxt.json | 56 --------------- libs/jacdac/shims.d.ts | 53 -------------- pxtarget.json | 20 ++++-- 10 files changed, 35 insertions(+), 271 deletions(-) delete mode 100755 libs/jacdac/_locales/jacdac-jsdoc-strings.json delete mode 100755 libs/jacdac/_locales/jacdac-strings.json delete mode 100755 libs/jacdac/pxt.json delete mode 100755 libs/jacdac/shims.d.ts diff --git a/libs/accelerometer/pxt.json b/libs/accelerometer/pxt.json index c68a30ff..95b0ce90 100644 --- a/libs/accelerometer/pxt.json +++ b/libs/accelerometer/pxt.json @@ -1,32 +1,11 @@ { - "name": "accelerometer", - "description": "The accelerometer library", - "dependencies": { - "core": "file:../core" - }, - "files": [ - "README.md", - "accelerometer.cpp", - "accelhw.cpp", - "axis.h", - "gesture.ts", - "shims.d.ts", - "enums.d.ts", - "ns.ts", - "pxtparts.json", - "part.svg" - ], - "testFiles": [ - "test.ts" - ], - "public": true, "additionalFilePath": "../accelerometer_custom", "yotta": { "optionalConfig": { - "PXT_SUPPORT_LIS3DH": 1, - "PXT_SUPPORT_MMA8653": 1, - "PXT_SUPPORT_MMA8453": 1, - "PXT_SUPPORT_FXOS8700": 1, + "PXT_SUPPORT_LIS3DH": 0, + "PXT_SUPPORT_MMA8653": 0, + "PXT_SUPPORT_MMA8453": 0, + "PXT_SUPPORT_FXOS8700": 0, "PXT_SUPPORT_MPU6050": 1 }, "userConfigs": [ diff --git a/libs/accelerometer/shims.d.ts b/libs/accelerometer/shims.d.ts index 9ecb9f1f..d0bbb4bb 100644 --- a/libs/accelerometer/shims.d.ts +++ b/libs/accelerometer/shims.d.ts @@ -29,14 +29,6 @@ declare namespace input { //% weight=42 blockGap=8 shim=input::acceleration function acceleration(dimension: Dimension): int32; - /** - * Get the temperature in Celsius or Fahrenheit degrees. - */ - //% blockId=device_temperature block="temperature in c" - //% parts="accelerometer" - //% weight=26 shim=input::temperature - function temperature(): int32; - /** * The pitch or roll of the device, rotation along the ``x-axis`` or ``y-axis``, in degrees. * @param kind TODO diff --git a/libs/accelerometer_custom/accelhw.cpp b/libs/accelerometer_custom/accelhw.cpp index 35ed3797..c140ba01 100644 --- a/libs/accelerometer_custom/accelhw.cpp +++ b/libs/accelerometer_custom/accelhw.cpp @@ -36,7 +36,7 @@ #endif #ifndef PXT_SUPPORT_MPU6050 -#define PXT_SUPPORT_MPU6050 0 +#define PXT_SUPPORT_MPU6050 1 #endif #if PXT_SUPPORT_MPU6050 #include "MPU6050.h" @@ -186,11 +186,19 @@ class WAccel { }; -SINGLETON_IF_PIN(WAccel, ACCELEROMETER_INT); +//SINGLETON_IF_PIN(WAccel, ACCELEROMETER_INT); +static WAccel *instAcc; codal::Accelerometer *getAccelerometer() { - auto wacc = getWAccel(); - return wacc ? wacc->acc : NULL; + // auto wacc = getWAccel(); + // return wacc ? wacc->acc : NULL; + if (instAcc) + return instAcc->acc; + if (LOOKUP_PIN(ACCELEROMETER_INT) || LOOKUP_PIN(ACCELEROMETER_SDA)) { + instAcc = new WAccel(); + return instAcc->acc; + } + return NULL; } } // namespace pxt diff --git a/libs/accelerometer_custom/pxt.json b/libs/accelerometer_custom/pxt.json index ec3543e4..1b4c73b0 100644 --- a/libs/accelerometer_custom/pxt.json +++ b/libs/accelerometer_custom/pxt.json @@ -11,8 +11,7 @@ "enums.d.ts", "ns.ts", "pxtparts.json", - "part.svg", - "jacdac.ts" + "part.svg" ], "testFiles": [ "test.ts" diff --git a/libs/core---nrf52/led.cpp b/libs/core---nrf52/led.cpp index d8d8a27f..a9a1af2e 100644 --- a/libs/core---nrf52/led.cpp +++ b/libs/core---nrf52/led.cpp @@ -4,7 +4,7 @@ extern TeknikioDevice bluebird; -namespace pxt { +namespace pxt { void initTeknikio() { bluebird.init(); @@ -44,7 +44,7 @@ namespace led { //% x.min=0 x.max=4 y.min=0 y.max=5 //% x.fieldOptions.precision=1 y.fieldOptions.precision=1 void plot(int x, int y) { - bluebird.display.image.setPixelValue(x, y, 0xff); + //bluebird.display.image.setPixelValue(x, y, 0xff); } @@ -59,7 +59,7 @@ namespace led { //% x.min=0 x.max=4 y.min=0 y.max=5 //% x.fieldOptions.precision=1 y.fieldOptions.precision=1 void unplot(int x, int y) { - bluebird.display.image.setPixelValue(x, y, 0); + //bluebird.display.image.setPixelValue(x, y, 0); } /** @@ -74,6 +74,6 @@ namespace led { //% x.fieldOptions.precision=1 y.fieldOptions.precision=1 //% advanced=true int pointBrightness(int x, int y) { - return bluebird.display.image.getPixelValue(x, y); + return 5;//bluebird.display.image.getPixelValue(x, y); } } \ No newline at end of file diff --git a/libs/jacdac/_locales/jacdac-jsdoc-strings.json b/libs/jacdac/_locales/jacdac-jsdoc-strings.json deleted file mode 100755 index 9e528866..00000000 --- a/libs/jacdac/_locales/jacdac-jsdoc-strings.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "JDGesture.EightG": "Raised when a 8G shock is detected", - "JDGesture.FaceDown": "Raised when the screen is pointing up and the board is horizontal", - "JDGesture.FaceUp": "Raised when the screen faces up", - "JDGesture.FreeFall": "Raised when the board is falling!", - "JDGesture.Shake": "Raised when shaken", - "JDGesture.SixG": "Raised when a 6G shock is detected", - "JDGesture.ThreeG": "Raised when a 3G shock is detected", - "JDGesture.TiltDown": "Raised when the device tilts down", - "JDGesture.TiltLeft": "Raised when the screen is pointing left", - "JDGesture.TiltRight": "Raised when the screen is pointing right", - "JDGesture.TiltUp": "Raised when the device tilts up", - "JDGesture.TwoG": "Raised when a 2g move (or step) is detected", - "jacdac": "A Joint Asynchronous Communications, Device Agnostic Control.", - "jacdac.Client.requiredDeviceName": "Get the required device names\n \nSet the required device name", - "jacdac.Client.requiredDeviceName@set": "Get the required device names\n \nSet the required device name", - "jacdac.Client.requiredDeviceUuid": "Set required device uuid\n \nSets the required device name", - "jacdac.Client.requiredDeviceUuid@set": "Set required device uuid\n \nSets the required device name", - "jacdac.ControllerClient.onStateUpdate": "Register code to run when the state is about to be sent", - "jacdac.JACDAC": "A packet", - "jacdac.JDControlService.isEnumerated": "*", - "jacdac.JDControlService.isEnumerating": "*", - "jacdac.JDControlService.startDeviceTimer": "Timer callback every 500 ms", - "jacdac.MessageBusService": "A driver that listens for message bus events", - "jacdac.SensorHost": "JacDac service running on sensor and streaming data out", - "jacdac.Service.start": "Registers and starts the driver", - "jacdac.Service.stop": "Unregister and stops the driver", - "jacdac.broadcastEvent": "Pipes specific events through JACDAC", - "jacdac.consoleService": "Starts and returns the console service", - "jacdac.devices": "Gets a snapshot of the device list", - "jacdac.identification": "The identitifiation service", - "jacdac.instance": "Gets the JACDAC instance", - "jacdac.isConnected": "Gets a value that indicates if the JACDAC bus is connected.", - "jacdac.isRunning": "Gets a value that indicates if JACDAC is running.", - "jacdac.onReceivedMessage": "Registers code to run for a particular message", - "jacdac.onReceivedMessage|param|msg": "@param handler ", - "jacdac.raiseEvent": "Sends an event over JacDac", - "jacdac.sendMessage": "Broadcasts a message over JacDac", - "jacdac.setDeviceName": "Sets the name of the current device on the JACDAC bus", - "jacdac.setDeviceName|param|name": "name of the device" -} \ No newline at end of file diff --git a/libs/jacdac/_locales/jacdac-strings.json b/libs/jacdac/_locales/jacdac-strings.json deleted file mode 100755 index 8b42dda2..00000000 --- a/libs/jacdac/_locales/jacdac-strings.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "JDButtonEvent.Click|block": "click", - "JDButtonEvent.Down|block": "down", - "JDButtonEvent.LongClick|block": "long click", - "JDButtonEvent.Up|block": "up", - "JDDimension.Strength|block": "strength", - "JDDimension.X|block": "x", - "JDDimension.Y|block": "y", - "JDDimension.Z|block": "z", - "JDGesture.EightG": "Raised when a 8G shock is detected", - "JDGesture.EightG|block": "8g", - "JDGesture.FaceDown": "Raised when the screen is pointing up and the board is horizontal", - "JDGesture.FaceDown|block": "face down", - "JDGesture.FaceUp": "Raised when the screen faces up", - "JDGesture.FaceUp|block": "face up", - "JDGesture.FreeFall": "Raised when the board is falling!", - "JDGesture.FreeFall|block": "free fall", - "JDGesture.Shake": "Raised when shaken", - "JDGesture.Shake|block": "shake", - "JDGesture.SixG": "Raised when a 6G shock is detected", - "JDGesture.SixG|block": "6g", - "JDGesture.ThreeG": "Raised when a 3G shock is detected", - "JDGesture.ThreeG|block": "3g", - "JDGesture.TiltDown": "Raised when the device tilts down", - "JDGesture.TiltDown|block": "tilt down", - "JDGesture.TiltLeft": "Raised when the screen is pointing left", - "JDGesture.TiltLeft|block": "tilt left", - "JDGesture.TiltRight": "Raised when the screen is pointing right", - "JDGesture.TiltRight|block": "tilt right", - "JDGesture.TiltUp": "Raised when the device tilts up", - "JDGesture.TiltUp|block": "tilt up", - "JDGesture.TwoG": "Raised when a 2g move (or step) is detected", - "JDGesture.TwoG|block": "2g (step)", - "JDLightAnimation.ColorWipe|block": "color wipe", - "JDLightAnimation.Comet|block": "comet", - "JDLightAnimation.Rainbow|block": "rainbow", - "JDLightAnimation.RunningLights|block": "running lights", - "JDLightAnimation.Sparkle|block": "sparkle", - "JDLightAnimation.TheaterChase|block": "theater chase", - "JDLightCondition.Bright|block": "bright", - "JDLightCondition.Dark|block": "dark", - "JDSwitchDirection.Left|block": "left", - "JDSwitchDirection.Right|block": "right", - "jacdac.ControllerClient.AIsPressed@set|block": "A is pressed", - "jacdac.ControllerClient.AIsPressed|block": "A is pressed", - "jacdac.ControllerClient.BIsPressed@set|block": "B is pressed", - "jacdac.ControllerClient.BIsPressed|block": "B is pressed", - "jacdac.ControllerClient.downIsPressed@set|block": "down is pressed", - "jacdac.ControllerClient.downIsPressed|block": "down is pressed", - "jacdac.ControllerClient.leftIsPressed@set|block": "left is pressed", - "jacdac.ControllerClient.leftIsPressed|block": "left is pressed", - "jacdac.ControllerClient.onStateUpdate|block": "on %controller state update", - "jacdac.ControllerClient.rightIsPressed@set|block": "right is pressed", - "jacdac.ControllerClient.rightIsPressed|block": "right is pressed", - "jacdac.ControllerClient.upIsPressed@set|block": "up is pressed", - "jacdac.ControllerClient.upIsPressed|block": "up is pressed", - "jacdac.Service.start|block": "start %service", - "jacdac.Service.stop|block": "stop %service", - "jacdac.broadcastEvent|block": "broadcast events|from %src|with value %value", - "jacdac.controllerClient|block": "controller client", - "jacdac.messageBusService|block": "message bus service", - "jacdac.onReceivedMessage|block": "on jacdac $msg received", - "jacdac.raiseEvent|block": "raise event|from %src|with value %value", - "jacdac.sendMessage|block": "jacdac send $msg", - "jacdac.setDeviceName|block": "jacdac set device name to $name", - "jacdac|block": "jacdac", - "{id:category}Jacdac": "Jacdac", - "{id:group}Broadcast": "Broadcast", - "{id:group}Control": "Control", - "{id:group}Controller": "Controller", - "{id:group}Services": "Services" -} \ No newline at end of file diff --git a/libs/jacdac/pxt.json b/libs/jacdac/pxt.json deleted file mode 100755 index 728eab2e..00000000 --- a/libs/jacdac/pxt.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "jacdac", - "description": "Plug and play single wire serial protocol - beta", - "dependencies": { - "core": "file:../core" - }, - "files": [ - "configurationservice.ts", - "consoleservice.ts", - "consts.ts", - "control.ts", - "controldebugview.ts", - "crc.ts", - "debugservice.ts", - "debugview.ts", - "debugviews.ts", - "devicemanager.ts", - "diagnostics.ts", - "ifaces.ts", - "jacdac.ts", - "rand.ts", - "rngservice.ts", - "service.ts", - "structs.ts", - "makecodeoptions.ts", - "makecodejacdac.ts", - "jacdac.cpp", - "shims.d.ts", - "config.ts", - "driver.ts", - "sensordriver.ts", - "jacdac.svg", - "pxtparts.json", - "actuator.ts", - "messagebus.ts", - "jacdacidentification.ts", - "controllerclient.ts", - "ns.ts", - "README.md" - ], - "testFiles": [ - "test.ts" - ], - "public": true, - "additionalFilePath": "../../node_modules/pxt-common-packages/libs/jacdac", - "yotta": { - "userConfigs": [ - { - "description": "JACDAC WebUSB debugging.", - "config": { - "DEVICE_JACDAC_DEBUG": 1 - } - } - ] - } -} diff --git a/libs/jacdac/shims.d.ts b/libs/jacdac/shims.d.ts deleted file mode 100755 index 6494d89c..00000000 --- a/libs/jacdac/shims.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Auto-generated. Do not edit. -declare namespace jacdac { - - /** - * Gets the physical layer component id - **/ - //% shim=jacdac::__physId - function __physId(): int32; - - /** - * Write a buffer to the jacdac physical layer. - **/ - //% shim=jacdac::__physSendPacket - function __physSendPacket(buf: Buffer): void; - - /** - * Reads a packet from the queue. NULL if queue is empty - **/ - //% shim=jacdac::__physGetPacket - function __physGetPacket(): Buffer; - - /** - * Returns the connection state of the JACDAC physical layer. - **/ - //% shim=jacdac::__physIsConnected - function __physIsConnected(): boolean; - - /** - * Indicates if the bus is running - **/ - //% shim=jacdac::__physIsRunning - function __physIsRunning(): boolean; - - /** - * Starts the JACDAC physical layer. - **/ - //% shim=jacdac::__physStart - function __physStart(): void; - - /** - * Reads the diagnostics struct provided by the physical layer. Returns a buffer or NULL. - **/ - //% shim=jacdac::__physGetDiagnostics - function __physGetDiagnostics(): Buffer; - - /** - * Stops the JACDAC physical layer. - **/ - //% shim=jacdac::__physStop - function __physStop(): void; -} - -// Auto-generated. Do not edit. Really. diff --git a/pxtarget.json b/pxtarget.json index 8da84377..d6a4ae2a 100755 --- a/pxtarget.json +++ b/pxtarget.json @@ -90,12 +90,20 @@ ] }, "simulator": { - "autoRun": true, - "streams": false, - "aspectRatio": 1.0, - "parts": true, - "partsAspectRatio": 0.69, - "dynamicBoardDefinition": true + "autoRun": true, + "streams": false, + "aspectRatio": 1.0, + "parts": true, + "partsAspectRatio": 0.69, + "dynamicBoardDefinition": true, + "messageSimulators": { + "jacdac": { + "url": "https://microsoft.github.io/jacdac-docs/tools/makecode-sim?webusb=0&parentOrigin=$PARENT_ORIGIN$", + "localHostUrl": "http://localhost:8000/tools/makecode-sim?webusb=0&parentOrigin=$PARENT_ORIGIN$", + "aspectRatio": 0.89, + "permanent": true + } + } }, "cloud": { "workspace": false,