diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index be3590f8fc..abeaeeaf3e 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -18,7 +18,7 @@ You are in the wrong place! Here are some good places to start: -- Check out [Discussions](https://github.com/Moddable-OpenSource/moddable/discussions) to see if other developers are asking the same question. +- Check out [Discussions](https://github.com/Moddable-OpenSource/moddable/discussions) to see if other developers are asking the same question. - Search through the [Issues already created](https://github.com/Moddable-OpenSource/moddable/issues?q=is%3Aissue+). Maybe your question has come up before. - Read the [Documentation](https://github.com/Moddable-OpenSource/moddable/tree/public/documentation#moddable-sdk--documentation-overview). There's lots of detailed documentation of a wide range of topics. - Ask a question in our [chatroom on Gitter](https://gitter.im/embedded-javascript/moddable). diff --git a/contributed/ble/hid-peripheral/README.md b/contributed/ble/hid-peripheral/README.md index 3ba1e14668..7130373c29 100644 --- a/contributed/ble/hid-peripheral/README.md +++ b/contributed/ble/hid-peripheral/README.md @@ -1,4 +1,4 @@ -This folder contains a host and mods that demonstrate how to build BLE HID Keyboards and Media Controllers with the Moddable SDK. +This folder contains a host and mods that demonstrate how to build BLE HID Keyboards and Media Controllers with the Moddable SDK. For a high-level overview, refer to [this blog post](https://blog.moddable.com/blog/ble-keyboards-media/). This document is documentation for using the BLE HID Host to make new keyboard and media controller apps. @@ -20,9 +20,9 @@ An HID peripheral must describe its own input capabilities to the BLE central it The implemented HID Report Descriptor is provided for reference at the end of this document. -## BLE HID Host API +## BLE HID Host API -### Host Events +### Host Events Three events are available on the BLE HID Host's `application` object and can be triggered by the UI mod to send keystrokes/button presses to a connected BLE Central: @@ -130,7 +130,7 @@ Send a quick tap of the `Mute` HID Consumer Device media key to the BLE Central: application.delegate("doKeyTap", {hidCode: HIDKEYS.MUTE.HID}); ``` -## HID Report Descriptor +## HID Report Descriptor Experienced HID developers may want to review the HID Report Descriptor used by the BLE HID Host. The report follows (annotations courtesy of [https://eleccelerator.com/usbdescreqparser/](https://eleccelerator.com/usbdescreqparser/)): @@ -187,4 +187,4 @@ Experienced HID developers may want to review the HID Report Descriptor used by 0x09, 0xB9, // Usage (Shuffle) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection -``` \ No newline at end of file +``` diff --git a/contributed/giphy/readme.md b/contributed/giphy/readme.md index 846ccdf537..56aa60e8c2 100644 --- a/contributed/giphy/readme.md +++ b/contributed/giphy/readme.md @@ -22,9 +22,9 @@ For more information on the implementation, see the blog post [GIPHY Goes to ESP cd $MODDABLE/contributed/giphy mcconfig -d -m -p esp32/moddable_two ``` - + > **Note:** Instead of putting your Wi-Fi network credentials and Giphy API key in the app manifest, you can also specify them in the `mcconfig` command: -> +> > ```text > mcconfig -d -m -p esp32/moddable_two ssid="YOUR_SSID_HERE" password="YOUR_PASSWORD_HERE" apiKey="YOUR_API_KEY_HERE" -> ``` \ No newline at end of file +> ``` diff --git a/contributed/modClock/readme.md b/contributed/modClock/readme.md index 49f6754ba5..9bce4bd432 100644 --- a/contributed/modClock/readme.md +++ b/contributed/modClock/readme.md @@ -2,4 +2,4 @@ -A classic LED style clock built using the Moddable SDK. For more information, see the [Clock Project](https://blog.moddable.com/blog/clock-project/) blog post. \ No newline at end of file +A classic LED style clock built using the Moddable SDK. For more information, see the [Clock Project](https://blog.moddable.com/blog/clock-project/) blog post. diff --git a/contributed/serial/SerialModule.md b/contributed/serial/SerialModule.md index a4235e9d18..8ebeddfc76 100644 --- a/contributed/serial/SerialModule.md +++ b/contributed/serial/SerialModule.md @@ -26,7 +26,7 @@ The `Serial` constructor takes its configuration information from the **manifest let serial = new Serial(); - + ### Configuration Configuration of the serial port is done in the **manifest.json** file. @@ -53,15 +53,15 @@ Configuration of the serial port is done in the **manifest.json** file. ## Blocking I/O - + A `timeout` can be set for blocking reads. The units are milliseconds: serial.setTimeout(10000); - + > If a read operation is not fulfilled by the timeout, the call will return with a partial read. #### Reading - + You can read a number of bytes: let str = serial.readBytes(10); @@ -101,19 +101,19 @@ You can write strings with an optional starting and ending position: serial.write("Hello"); // Hello serial.write("Hello", 3); // llo - serial.write("Hello", 1, 1); // e + serial.write("Hello", 1, 1); // e serial.write("Hello", -2); // lo - + You can write an array buffer with an optional starting and ending position. let buffer = new ArrayBuffer(6); let chars = new Uint8Array(buffer); - + // fill buffer with "test 1" chars[0] = 0x74; chars[1] = 0x65; chars[2] = 0x73; chars[3] = 0x74; chars[4] = 0x20; chars[5] = 0x31; - + serial.write(buffer); // test 1 serial.write(buffer, 4); // test serial.write(buffer, 1, 3); // est @@ -145,8 +145,8 @@ key | default | description Call `serial.poll` with no dictionary to stop polling. serial.poll(); - - + + ## Examples diff --git a/contributed/serial/drivers/sim7100/SIM7100.md b/contributed/serial/drivers/sim7100/SIM7100.md index 23be3e0076..80518fed7a 100644 --- a/contributed/serial/drivers/sim7100/SIM7100.md +++ b/contributed/serial/drivers/sim7100/SIM7100.md @@ -54,7 +54,7 @@ key | default | description ### Stopping the SIM7100 -You can stop the SIM7100 by calling its `stop` function. +You can stop the SIM7100 by calling its `stop` function. ```js sim7100.stop() @@ -105,7 +105,7 @@ Set an `onGPSEnabled` function to be notified when it is ready for commands. The sim7100.onGPSEnabled = function(device) { device.getGPS(); // read GPS once. } - + sim7100.enableGPS(); ``` @@ -117,7 +117,7 @@ To get a GPS reading, set an `onGPSChanged` function to receive the results and sim7100.onGPSChanged = function(gps) { trace(`${gps.seq}) lat:${gps.lat} lon:${gps.lon}\n`); } - + sim7100.getGPS(); ``` @@ -152,7 +152,7 @@ To disable GPS, set an optional `onGPSDisabled` function to be notified when it sim7100.onGPSDisabled = function(device) { trace("GPS done.\n"); } - + sim7100.disableGPS(); ``` @@ -189,4 +189,4 @@ To change the brightness of the LEDs, call `ledBrightness` with a value between [sim7100gps](examples/sim7100gps) shows asynchronous GPS message reception. ### gpsmap -[gpsmap](examples/gpsmap) uses the SIM7100 to fetch the current GPS latitude and longitude and presents a map-tile on the moddable_zero screen. \ No newline at end of file +[gpsmap](examples/gpsmap) uses the SIM7100 to fetch the current GPS latitude and longitude and presents a map-tile on the moddable_zero screen. diff --git a/contributed/window-display-moddable-one/readme.md b/contributed/window-display-moddable-one/readme.md index 4260a42f1e..cdaa7eba1f 100644 --- a/contributed/window-display-moddable-one/readme.md +++ b/contributed/window-display-moddable-one/readme.md @@ -2,4 +2,4 @@ ![](https://blog.moddable.com/blog/wp-content/uploads/2020/12/animation-preview-sm.gif) -This example shows a series of eye-catching animations. It's designed to run on Moddable One, but will also run on Moddable Two and other development boards. For more information about the implementation, see the blog post [Animations on a Display Powered by a $1 Wi-Fi Controller](https://blog.moddable.com/blog/animations-on-microcontrollers/). \ No newline at end of file +This example shows a series of eye-catching animations. It's designed to run on Moddable One, but will also run on Moddable Two and other development boards. For more information about the implementation, see the blog post [Animations on a Display Powered by a $1 Wi-Fi Controller](https://blog.moddable.com/blog/animations-on-microcontrollers/). diff --git a/contributing.md b/contributing.md index 8339299927..2a3bdcad8c 100644 --- a/contributing.md +++ b/contributing.md @@ -14,14 +14,14 @@ Want to contribute to the Moddable SDK? Great! We welcome all kinds of contribut If you find a bug or have trouble using the Moddable SDK, please [open an issue](https://github.com/Moddable-OpenSource/moddable/issues). We'll respond as quickly as practical. By open an issue, other developers will benefit from the answers to your questions. -Before you open an issue, search the repository to see if someone else has already reported it. If they have, please add comments to the existing thread. +Before you open an issue, search the repository to see if someone else has already reported it. If they have, please add comments to the existing thread. ## Requesting features To request a new feature, please [open an issue](https://github.com/Moddable-OpenSource/moddable/issues). -Before you open an issue, search the repository to see if someone else has already requested the feature. If they have, please add comments to the existing thread about why you'd like to see the feature added. +Before you open an issue, search the repository to see if someone else has already requested the feature. If they have, please add comments to the existing thread about why you'd like to see the feature added. ## Submitting pull requests @@ -37,4 +37,4 @@ Before we can accept pull requests, we ask that you complete a Contributor Licen We'd love to see what you make with the Moddable SDK! Please share with us on Twitter [@moddabletech](https://www.twitter.com/moddabletech) or our [chatroom on Gitter](https://gitter.im/embedded-javascript/moddable). -We'd also love to help share your work. The [`contributed` directory](./contributed) of this repository contains community-contributed modules and code. Feel free to submit a pull request to add your projects to this directory. \ No newline at end of file +We'd also love to help share your work. The [`contributed` directory](./contributed) of this repository contains community-contributed modules and code. Feel free to submit a pull request to add your projects to this directory. diff --git a/documentation/base/base.md b/documentation/base/base.md index 962f3f755e..79ca6161c5 100644 --- a/documentation/base/base.md +++ b/documentation/base/base.md @@ -55,7 +55,7 @@ The callback function receives the timer id as the first argument. ### `Timer.repeat(callback, interval)` -A repeating timer is called continuously until stopped using the `Timer.clear` function. +A repeating timer is called continuously until stopped using the `Timer.clear` function. ```js Timer.repeat(id => trace("repeat fired\n"), 1000); @@ -165,7 +165,7 @@ const stop = Time.ticks; trace(`Operation took ${Time.delta(start, stop)} milliseconds\n`); ``` -On devices that supports multiple concurrent JavaScript virtual machines (for example, using Workers), the clock used to determine the value of the `ticks` property is the same across all virtual machines. This allows `tick` values created in one machine to be compared with values from another. +On devices that supports multiple concurrent JavaScript virtual machines (for example, using Workers), the clock used to determine the value of the `ticks` property is the same across all virtual machines. This allows `tick` values created in one machine to be compared with values from another. The range of the value depends on the host. On most microcontrollers, the value is a signed 32-bit integer. On the simulator, it is a positive 64-bit floating point value. To determine the difference between two `ticks` values, use `Time.delta()` which is guaranteed to give a correct result for the host. @@ -241,7 +241,7 @@ Debug.gc(false); // disable garbage collector - **Source code:** [uuid](../../modules/base/uuid) -The `UUID` class provides a single function to generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) string. +The `UUID` class provides a single function to generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) string. ```js import UUID from "uuid"; @@ -265,7 +265,7 @@ let value = UUID(); // 1080B49C-59FC-4A32-A38B-DE7E80117842 - **Source code:** [deepEqual](../../modules/base/deepEqual) - **Tests:** [deepEqual](../../tests/modules/base/deepEqual) -The `deepEqual` function implements a deep comparison between two JavaScript object. +The `deepEqual` function implements a deep comparison between two JavaScript object. ```js import deepEqual from "deepEqual"; @@ -296,13 +296,13 @@ The known differences between the Moddable SDK implementation and Node.js will n - **Source code:** [structuredClone](../../modules/base/structuredClone) - **Tests:** [structuredClone](../../tests/modules/base/structuredClone) -The `structuredClone` function creates a deep copy of a JavaScript object. +The `structuredClone` function creates a deep copy of a JavaScript object. ```js import structuredClone from "structuredClone"; ``` -The `structuredClone` function in the Moddable SDK implements the [algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) defined by WHATWG for the web platform as much as practical, including circular references and the `transferables` option. +The `structuredClone` function in the Moddable SDK implements the [algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) defined by WHATWG for the web platform as much as practical, including circular references and the `transferables` option. ```js const a = {a: 1, b: Uint8Array.of(1, 2, 3,)} @@ -361,7 +361,7 @@ for (let i = 1; true; i++) { ### Instrumentation items -The table below describes the instrumented items that are available. The following instrumented items are reset at one second intervals: Pixels Drawn, Frames Drawn, Poco Display List Used, Piu Command List Used, Network Bytes Read, Network Bytes Written, and Garbage Collection Count. +The table below describes the instrumented items that are available. The following instrumented items are reset at one second intervals: Pixels Drawn, Frames Drawn, Poco Display List Used, Piu Command List Used, Network Bytes Read, Network Bytes Written, and Garbage Collection Count. | Name | Long Description | | ---: | :--- | diff --git a/documentation/base/setup.md b/documentation/base/setup.md index c090cce9e1..40693a525b 100644 --- a/documentation/base/setup.md +++ b/documentation/base/setup.md @@ -29,7 +29,7 @@ To minimize RAM use and speed start-up time, the main module and any setup modul ## Additional notes -- The idea for setup modules is loosely modeled on the setup function in the Arduino application model. +- The idea for setup modules is loosely modeled on the setup function in the Arduino application model. - The simulator implicitly performs the work of setup already, initializing the screen global variable before running the main module. - The setup modules are only run on the first (main) virtual machine instantiated. For example, when using Workers, the setup modules are not run in the workers. - Sometimes it is useful to remove a setup module provided by the host, for example to replace the default `setup/network` module so that the application script can manage the Wi-Fi connection itself. This is accomplished using the `"~"` option of manifests. diff --git a/documentation/base/worker.md b/documentation/base/worker.md index 7d144c77ab..59c7b6c228 100644 --- a/documentation/base/worker.md +++ b/documentation/base/worker.md @@ -29,7 +29,7 @@ Scripts import the `Worker` class to be able to create a new worker. To launch a worker, create an instance of the `Worker` class, passing the name of the module to invoke when the worker starts to run. In the following example, the module run at worker start is `simpleworker`. let aWorker = new Worker("simpleworker"); - + The call to the `Worker` constructor returns only after execution of the specified module completes. If the worker module generates an exception during this step, an exception is propagated so that the call to `new Worker` throws an exception. This behavior means that the invoking virtual machine blocks until the new worker virtual machine has completed initialization. Consequently, any operations performed in a newly instantiated virtual machine should be relatively brief. ### Launching a worker with memory configuration @@ -39,7 +39,7 @@ The previous example launches the worker with the default memory configuration. {allocation: 8192, stackCount: 64, slotCount: 64}); ### Sending a message to a worker -Messages to workers are JavaScript objects and binary data. +Messages to workers are JavaScript objects and binary data. aWorker.postMessage({hello: "world", count: 12}); aWorker.postMessage(new ArrayBuffer(12)); @@ -77,7 +77,7 @@ When the Worker constructor is called, the module at the path specified (`simple let count = 1; let state = INITIALIZED; - + self.onmessage = function (message) { trace(message, "\n"); } @@ -123,7 +123,7 @@ The `postMessage` function queues a message for delivery to the worker. Messages Messages are delivered in the same order they are sent. -Messages are passed by copy (with a few exceptions, such as `SharedArrayBuffer`, so the size of the message should be as small as practical. If the memory allocation fails, `postMessage` throws an exception. +Messages are passed by copy (with a few exceptions, such as `SharedArrayBuffer`, so the size of the message should be as small as practical. If the memory allocation fails, `postMessage` throws an exception. #### onmessage property The worker `onmessage` property contains a function which receives messages from the worker. @@ -143,7 +143,7 @@ The `SharedWorker` class is an API for working with shared virtual machines. The Scripts import the `SharedWorker` class to be able to connect to a shared worker, creating the shared worker if it is not currently instantiated. import {SharedWorker} from "worker"; - + **Note**: Examples and documentation needed. ## Scheduling diff --git a/documentation/commodetto/commodetto.md b/documentation/commodetto/commodetto.md index 895d7333e0..cadc9aefb3 100644 --- a/documentation/commodetto/commodetto.md +++ b/documentation/commodetto/commodetto.md @@ -26,7 +26,7 @@ This document provides a high-level overview of the parts of Commodetto, informa * [JPEG](#jpeg) * [PNG](#png) * [BMFont](#bmfont) -* [Rendering](#rendering) +* [Rendering](#rendering) * [Render class](#render-class) * [Pixel format conversion](#pixel-format-conversion) * [Convert Class](#convert-class) @@ -101,7 +101,7 @@ typedef enum { | kCommodettoBitmapMonochrome | Pixels are 1-bit data, packed into bytes in which the high bit of the byte is the leftmost pixel. | kCommodettoBitmapGray16 | Pixels are 4-bit data, where 0 represents white, 15 represents black, and the values in between are proportionally interpolated gray levels. The pixels are packed into bytes in which the high nybble is the leftmost pixel. | kCommodettoBitmapGray16 \| kCommodettoBitmapPacked | Pixels are the same as in `kCommodettoBitmapGray16`, and compressed using a weighted RLE algorithm. -| kCommodettoBitmapGray256 | Pixels are 8-bit data, where 0 represents white, 255 represents black, and the values in between are proportionally interpolated gray levels. +| kCommodettoBitmapGray256 | Pixels are 8-bit data, where 0 represents white, 255 represents black, and the values in between are proportionally interpolated gray levels. | kCommodettoBitmapRGB332 | Pixels are 8-bit data, with packed RGB values. The high three bits are red, followed by three bits of green, and two bits of blue. | kCommodettoBitmapRGB565LE | Pixels are 16-bit data, with packed RGB values. The high five are red, followed by six bits of green, and five bits of blue. The 16-bit value is stored in little-endian byte order. | kCommodettoBitmapRGB565BE | Pixels are 16-bit data, with packed RGB values. The high five are red, followed by six bits of green, and five bits of blue. The 16-bit value is stored in big-endian byte order. @@ -288,7 +288,7 @@ A `PixelsOut` instance is initialized with a dictionary of values. The dictionar ```javascript let display = new SPIOut({width: 320, height: 240, pixelFormat: Bitmap.RGB565BE, orientation: 90, dataPin: 30}); - + let offScreen = new BufferOut({width: 40, height: 40, pixelFormat: Bitmap.RGB565LE}); @@ -304,15 +304,15 @@ Once constructed, a `PixelsOut` instance can receive pixels. Three function call let x = 10, y = 20; let width = 40, height = 50; display.begin(x, y, width, height); - + let scanLine = new ArrayBuffer(display.pixelsToBytes(width)); for (let line = 0; line < height; line++) display.send(scanLine); - + display.end(); ``` -The `begin` call indicates the area of the `PixelsOut` bitmap to update. Following that are one or more calls to `send` that contain the pixels. In the example above, `send` is called 50 times, each time with a buffer of 40 black (all 0) pixels. The number of bytes of data passed by the combined calls to `send` must be exactly the number of bytes needed to fill the area specified in the call to `begin`. Once all data has been provided, call `end`. +The `begin` call indicates the area of the `PixelsOut` bitmap to update. Following that are one or more calls to `send` that contain the pixels. In the example above, `send` is called 50 times, each time with a buffer of 40 black (all 0) pixels. The number of bytes of data passed by the combined calls to `send` must be exactly the number of bytes needed to fill the area specified in the call to `begin`. Once all data has been provided, call `end`. The `PixelsOut` API does not define when the data is transmitted to the output. Different `PixelsOut` subclasses implement it differently: some transmit the data immediately and synchronously, some use asynchronous transfers, and others buffer the data to display only when `end` is called. @@ -339,7 +339,7 @@ class PixelsOut { ##### `constructor(dictionary)` -The `PixelsOut` constructor takes a single argument: a dictionary of property names and values. The `PixelsOut` base class defines three properties that are defined for all subclasses of `PixelsOut`: +The `PixelsOut` constructor takes a single argument: a dictionary of property names and values. The `PixelsOut` base class defines three properties that are defined for all subclasses of `PixelsOut`: | Name | Description | | :---: | :--- | @@ -386,7 +386,7 @@ is almost the same as this: out.end(); out.begin(10, 20, 30, 40); ``` - + The difference is that when `continue` is used, all output pixels are part of the same frame, whereas with `end`/`begin` pixels transmitted before `end` are part of one frame and pixels transmitted after it are part of the following frame. For some outputs--for example, `BufferOut`--there is no difference. For others--for example, a hardware-accelerated renderer--the results are visually different. @@ -423,7 +423,7 @@ The `adaptInvalid` function takes a rectangle argument specifying an area inside ##### `pixelsToBytes(count)` -The `pixelsToBytes` function calculates the number of bytes required to store the number of pixels specified by the `count` argument. The following allocates an `ArrayBuffer` corresponding to a single scanline of pixels: +The `pixelsToBytes` function calculates the number of bytes required to store the number of pixels specified by the `count` argument. The following allocates an `ArrayBuffer` corresponding to a single scanline of pixels: ```javascript let buffer = new ArrayBuffer(out.pixelsToBytes(width)); @@ -458,7 +458,7 @@ class SPIOut extends PixelsOut ### BufferOut Class -`BufferOut` is a subclass of `PixelsOut` that implements an offscreen in-memory bitmap. +`BufferOut` is a subclass of `PixelsOut` that implements an offscreen in-memory bitmap. ```javascript class BufferOut extends PixelsOut; @@ -659,7 +659,7 @@ while (decoder.ready) { The PNG image format is commonly used for the assets of user interface elements such as buttons and sliders. Because the PNG file format is heavily compressed, PNG images must be decompressed to a `BufferOut` instance for use. Also because of the compression used in PNG, a significant amount of memory is required for decompressing the image. Nonetheless, because PNG is so common in user interface work, Commodetto implements a PNG module for use on devices and scenarios where it is practical. -The PNG decoder in Commodetto supports most variations of the PNG file format, with two exceptions: +The PNG decoder in Commodetto supports most variations of the PNG file format, with two exceptions: - Interlaced images are not supported, as interlacing is incompatible with progressive decoding. @@ -728,7 +728,7 @@ The PNG decoder uses up to 45 KB of memory while decoding an image. This amount ### BMFont -[BMFont](http://www.angelcode.com/products/bmfont/) is a format for storing bitmap fonts. It is widely used to embed distinctive fonts in games in a format that is efficiently rendered using OpenGL. BMFont is well designed and straightforward to support. Commodetto uses BMFont to store both anti-aliased and multicolor fonts. In addition, BMFont has good tool support--in particular the excellent [Glyph Designer](https://71squared.com/glyphdesigner), which converts macOS fonts to a Commodetto-compatible BMFont. For Windows and Linux users, the command line [bmfont](https://github.com/vladimirgamalyan/fontbm) has been used successfully. +[BMFont](http://www.angelcode.com/products/bmfont/) is a format for storing bitmap fonts. It is widely used to embed distinctive fonts in games in a format that is efficiently rendered using OpenGL. BMFont is well designed and straightforward to support. Commodetto uses BMFont to store both anti-aliased and multicolor fonts. In addition, BMFont has good tool support--in particular the excellent [Glyph Designer](https://71squared.com/glyphdesigner), which converts macOS fonts to a Commodetto-compatible BMFont. For Windows and Linux users, the command line [bmfont](https://github.com/vladimirgamalyan/fontbm) has been used successfully. BMFont stores a font's metrics data separately from the font's glyph atlas (bitmap). This means that loading a BMFont requires two steps: loading the metrics and loading the glyph atlas. BMFont allows the metrics data to be stored in a variety of formats, including text, XML, and binary. Commodetto supports the binary format for metrics. @@ -744,7 +744,7 @@ palatino36.bitmap = parseBMP(new Resource("palatino36.bmp"); After the metrics are prepared with `parseBMF`, the glyph atlas is prepared using `parseBMP` and is attached to the metrics as the `bitmap` property. - BMFont files with discontiguous ranges of characters are supported. Commodetto may be configured to use the kerning data that may be prseent in a BMFont, though it is disabled by default. + BMFont files with discontiguous ranges of characters are supported. Commodetto may be configured to use the kerning data that may be prseent in a BMFont, though it is disabled by default. For anti-aliased text, the BMP file containing the glyph atlas bitmap must be in 4-bit gray format. For multicolor text, the bitmap must be in `Bitmap.default` format (e.g. the pixel format Commodetto is configured to render to). @@ -794,10 +794,10 @@ The following example shows using the Poco renderer with `SPIOut` to render a sc let display = new SPIOut({width: 320, height: 240, pixelFormat: Bitmap.RGB565LE, dataPin: 30}); let render = new Poco(display); - + let white = poco.makeColor(255, 255, 255); let red = poco.makeColor(255, 0, 0); - + render.begin(); render.fillRectangle(white, 0, 0, display.width, display.height); render.fillRectangle(red, 5, 5, 10, 10); @@ -827,7 +827,7 @@ Calling `begin` with no arguments is equivalent to calling it with `x` and `y` e ```javascript render.begin() ``` - + is equivalent to this: ```javascript diff --git a/documentation/commodetto/outline/Outlines.md b/documentation/commodetto/outline/Outlines.md index ed990e6acb..ef700d6aec 100644 --- a/documentation/commodetto/outline/Outlines.md +++ b/documentation/commodetto/outline/Outlines.md @@ -35,7 +35,7 @@ Projects using Outlines with Piu should include the `manifest_outline_piu.json` ## Building Paths -The `Outline` class has several different ways to build paths. +The `Outline` class has several different ways to build paths. ``` import Outline from "commodetto/outline"; @@ -56,8 +56,8 @@ The `Outline.CanvasPath.prototype` supports the following methods: - `moveTo(x, y)` - `quadraticCurveTo(cpx, cpy, x, y)` - `rect(x, y, w, h)` - -These methods are documented in the HTML specification under [Building Paths](https://html.spec.whatwg.org/multipage/canvas.html#building-paths). + +These methods are documented in the HTML specification under [Building Paths](https://html.spec.whatwg.org/multipage/canvas.html#building-paths). ![](./assets/CanvasPath.gif) [source](../../../examples/piu/outline/figures/CanvasPath/mod.js) @@ -82,7 +82,7 @@ The `Outline.FreeTypePath.prototype` has the following methods: - see [`FT_Stroker_CubicTo`](https://freetype.org/freetype2/docs/reference/ft2-glyph_stroker.html#ft_stroker_cubicto) - `endSubpath()`: - see [`FT_Stroker_EndSubPath`](https://freetype.org/freetype2/docs/reference/ft2-glyph_stroker.html#ft_stroker_endsubpath) -- `lineTo(x, y)`: +- `lineTo(x, y)`: - `x`, `y`: the destination point - see [`FT_Stroker_LineTo`](https://freetype.org/freetype2/docs/reference/ft2-glyph_stroker.html#ft_stroker_lineto) @@ -96,7 +96,7 @@ A static method that creates a polygon from a list of coordinates. | --- | --- | --- | | x0, y0, x1, y1 /* etc */ | number | the coordinates of the polygon vertices | -Returns a new path. +Returns a new path. ![](./assets/PolygonPath.gif) [source](../../../examples/piu/outline/figures/PolygonPath/mod.js) @@ -109,7 +109,7 @@ A static method that creates a rectangle with rounded corners. | x, y, width, height | number | the coordinates of the rectangle | | radius | number | the radius of the rounded corners | -Returns a new path. +Returns a new path. ![](./assets/RoundRectPath.gif) [source](../../../examples/piu/outline/figures/RoundRectPath/mod.js) @@ -121,7 +121,7 @@ A static method that creates a path from an SVG path string. | --- | --- | --- | | data | string | [the SVG path data](https://svgwg.org/svg2-draft/paths.html#PathData) | -Returns a new path. +Returns a new path. The SVG path data parser supports the following commands: @@ -138,7 +138,7 @@ Since a path is an array, if there are multiple paths in the SVG element, use `O ## Creating Outlines -The `Outline` class has static methods to create outlines by filling or stroking a path. +The `Outline` class has static methods to create outlines by filling or stroking a path. #### `Outline.fill(path, rule)` @@ -171,7 +171,7 @@ Returns a new outline, an instance of `Outline.prototype`. The `Outline` prototype has one getter to get the bounds of the outline, one method to clone outlines and three methods to transform outlines. -All transformations modify the outline's data and therefore can be irreversible because of the precision of coordinates. +All transformations modify the outline's data and therefore can be irreversible because of the precision of coordinates. #### `Outline.prototype.get bounds()` @@ -327,7 +327,7 @@ The Piu `shape` object is a `content` object that uses the fill color and the st By default, a `shape` object is empty, its fill outline and stroke outlines are `null`. Set the `fillOutline` or `strokeOutline` properties to change its fill outline or its stroke outline. -The measured width of a shape object is the maximum of its fill outline and stroke outline widths. The measured height of a shape object is the maximum of its fill outline and stroke outline heights. So changing the fill outline or the stroke outline of a `shape` object can reflow the layout of its containers. +The measured width of a shape object is the maximum of its fill outline and stroke outline widths. The measured height of a shape object is the maximum of its fill outline and stroke outline heights. So changing the fill outline or the stroke outline of a `shape` object can reflow the layout of its containers. > Usually the same path is used to create the fill outline with `Outline.fill` and the stroke outline with `Outline.stroke`. However, the `shape` object assumes no relationships between the two outlines. @@ -366,7 +366,7 @@ import {} from "piu/MC"; import {} from "piu/shape"; import {Outline} from "commodetto/outline"; ``` -Then we define the shapes outlines in the `onCreate` method of their behavior. +Then we define the shapes outlines in the `onCreate` method of their behavior. ### Frame and Dial @@ -376,7 +376,7 @@ The frame is just a white circle. class FrameBehavior extends Behavior { onCreate(shape) { const path = new Outline.CanvasPath(); - path.arc(120, 120, 120, 0, 2 * Math.PI); + path.arc(120, 120, 120, 0, 2 * Math.PI); shape.fillOutline = Outline.fill(path); } } diff --git a/documentation/commodetto/poco.md b/documentation/commodetto/poco.md index f3206b5ee6..9da6a09c03 100644 --- a/documentation/commodetto/poco.md +++ b/documentation/commodetto/poco.md @@ -203,7 +203,7 @@ poco.fillPattern(pattern, 28, 28, 63, 35, 21, 14, 7, 7); ### Gray Bitmap -This example uses `drawGray` to draw a 16-level gray image in several colors. `drawGray` treats the pixel values as alpha blending levels, blending the specified color with the background. +This example uses `drawGray` to draw a 16-level gray image in several colors. `drawGray` treats the pixel values as alpha blending levels, blending the specified color with the background. ```javascript poco.fillRectangle(gray, 0, 0, poco.width, poco.height); @@ -312,7 +312,7 @@ When complete, each approach generates the same result. ### Text -Poco supports the BMPFont format for fonts used to rendering text. BMFont is a gray or color font used in games for anti-aliased fonts. A BMFont consists of two files: the font metrics and the font image. +Poco supports the BMPFont format for fonts used to rendering text. BMFont is a gray or color font used in games for anti-aliased fonts. A BMFont consists of two files: the font metrics and the font image. The following example loads and draws a 36-point Palatino BMFont. @@ -466,7 +466,7 @@ Poco extends the `Render` dictionary with the `displayListLength` property, whic ```javascript import Poco from "commodetto/Poco"; - + let screen = ... // SPIOut instance let poco = new Poco(screen, {displayListLength: 4096}); ``` @@ -501,9 +501,9 @@ poco.clip() // Clip is entire PixelsOut area poco.end(); ``` -If the clip stack overflows or underflows, an exception is thrown from `end`. The clip stack must be empty when `end` is called or an exception is thrown. +If the clip stack overflows or underflows, an exception is thrown from `end`. The clip stack must be empty when `end` is called or an exception is thrown. -When calling `clip` with four arguments, the return value is `true` if the resulting area contains one or more pixels and `undefined` if the clip area is empty. +When calling `clip` with four arguments, the return value is `true` if the resulting area contains one or more pixels and `undefined` if the clip area is empty. > **Note:** `clip` and `origin` share the same stack, and so must be popped in the order they were pushed. @@ -511,7 +511,7 @@ When calling `clip` with four arguments, the return value is `true` if the resul #### `origin(x, y)` -Poco maintains an origin that is applied to all drawing operations. +Poco maintains an origin that is applied to all drawing operations. When `begin` is called, the origin is set to `{x: 0, y: 0}`. Poco maintains an origin stack, eliminating the need for applications to save and restore the current origin. Calling `origin` with two arguments offsets the current origin by the arguments; calling it with no arguments pops the origin stack, restoring the previous origin. @@ -524,7 +524,7 @@ poco.origin(); // Origin is {x: 0, y: 0} poco.end(); ``` -If the origin stack overflows or underflows, an exception is thrown from `end`. The origin stack must be empty when `end` is called, or an exception will be thrown. +If the origin stack overflows or underflows, an exception is thrown from `end`. The origin stack must be empty when `end` is called, or an exception will be thrown. > **Note:** Changing the origin does not change the clip rectangle. Note too that `clip` and `origin` share the same stack, and so must be popped in the order they were pushed. @@ -613,7 +613,7 @@ let red = poco.makeColor(255, 0, 0); let gray = poco.makeColor(128, 128, 128); let white = poco.makeColor(255, 255, 255); let icon = parseBMP(new Resource("icon.bmp")); - + poco.drawMonochrome(icon, red, white, 0, 5); // red foreground and white background poco.drawMonochrome(icon, gray, undefined, 0, 5); // only foreground pixels in gray poco.drawMonochrome(icon, undefined, red, 0, 5); // only background pixels in red @@ -748,7 +748,7 @@ The Poco C API may be used independently of Commodetto and its JavaScript API. I `PocoRecord` maintains state for Poco. Many of the fields are private to the implementation and should not be accessed directly by users of the library. The `PocoRecord` data structure should be initialized to 0, and the same `PocoRecord` structure must be passed to all Poco function calls. -The following fields in `PocoRecord` are public and can be accessed by users of the library. Poco expects these fields to be initialized by the users of the library before the first call to Poco is made. +The following fields in `PocoRecord` are public and can be accessed by users of the library. Poco expects these fields to be initialized by the users of the library before the first call to Poco is made. | Field | Description | | :---: | :--- | @@ -814,7 +814,7 @@ typedef struct { ##### `PocoBitmap` -The `PocoBitmap` structure contains the width and height of the bitmap in pixels, the format of the pixels in the bitmap, and a pointer to the pixel data. +The `PocoBitmap` structure contains the width and height of the bitmap in pixels, the format of the pixels in the bitmap, and a pointer to the pixel data. ```c typedef struct PocoBitmapRecord { diff --git a/documentation/crypt/crypt.md b/documentation/crypt/crypt.md index ce23e4fdee..cc9f5d868d 100644 --- a/documentation/crypt/crypt.md +++ b/documentation/crypt/crypt.md @@ -85,7 +85,7 @@ The `pemToDER` function transforms a certificate in PEM format (Base64 encoded A For PEM files containing more than one certificate, `pemToDER` converts only the first certificate. -This function is similar to the following `openssl` command line: +This function is similar to the following `openssl` command line: ``` openssl x509 -inform pem -in data.pem -out data.der -outform der diff --git a/documentation/data/data.md b/documentation/data/data.md index f785eabd86..3b13875b80 100644 --- a/documentation/data/data.md +++ b/documentation/data/data.md @@ -122,7 +122,7 @@ Include the module's manifest to use it in a project: #### `CRC8(polynomial [, initial [, reflectInput [, reflectOutput [, xorOutput]]]])` #### `CRC16(polynomial [, initial [, reflectInput [, reflectOutput [, xorOutput]]]])` -The `CRC8` and `CRC16` functions take a number of options used to specify the CRC checksum to calculate. +The `CRC8` and `CRC16` functions take a number of options used to specify the CRC checksum to calculate. | Parameter | Default | Description | | :---: | :---: | :--- | @@ -136,39 +136,39 @@ The `polynomial`, `initial` and `xorOutput` values are 8-bit integers for CRC8 a The [crc example](../../examples/data/crc/main.js) demonstrates the definition of the parameters for a number of common CRC checksums: -- `CRC-8` -- `CRC-8/CDMA2000` -- `CRC-8/DARC` -- `CRC-8/DVB-S2` -- `CRC-8/EBU` -- `CRC-8/I-CODE` -- `CRC-8/ITU` -- `CRC-8/MAXIM` -- `CRC-8/ROHC` -- `CRC-8/WCDM` -- `CRC-16/CCITT-FALSE` -- `CRC-16/ARC` -- `CRC-16/ARG-CCITT` -- `CRC-16/BUYPASS` -- `CRC-16/CDMA2000` -- `CRC-16/DDS-110` -- `CRC-16/DECT-R` -- `CRC-16/DECT-X` -- `CRC-16/DNP` -- `CRC-16/EN-13757` -- `CRC-16/GENIBUS` -- `CRC-16/MAXIM` -- `CRC-16/MCRF4XX` -- `CRC-16/RIELLO` -- `CRC-16/T10-DIF` -- `CRC-16/TELEDISK` -- `CRC-16/TMS37157` -- `CRC-16/USB` -- `CRC-A` -- `CRC-16/KERMIT` -- `CRC-16/MODBUS` -- `CRC-16/X-25` -- `CRC-16/XMODE` +- `CRC-8` +- `CRC-8/CDMA2000` +- `CRC-8/DARC` +- `CRC-8/DVB-S2` +- `CRC-8/EBU` +- `CRC-8/I-CODE` +- `CRC-8/ITU` +- `CRC-8/MAXIM` +- `CRC-8/ROHC` +- `CRC-8/WCDM` +- `CRC-16/CCITT-FALSE` +- `CRC-16/ARC` +- `CRC-16/ARG-CCITT` +- `CRC-16/BUYPASS` +- `CRC-16/CDMA2000` +- `CRC-16/DDS-110` +- `CRC-16/DECT-R` +- `CRC-16/DECT-X` +- `CRC-16/DNP` +- `CRC-16/EN-13757` +- `CRC-16/GENIBUS` +- `CRC-16/MAXIM` +- `CRC-16/MCRF4XX` +- `CRC-16/RIELLO` +- `CRC-16/T10-DIF` +- `CRC-16/TELEDISK` +- `CRC-16/TMS37157` +- `CRC-16/USB` +- `CRC-A` +- `CRC-16/KERMIT` +- `CRC-16/MODBUS` +- `CRC-16/X-25` +- `CRC-16/XMODE` ### `close()` @@ -277,8 +277,8 @@ The [inflate example](../../examples/data/inflate/main.js) demonstrates how to d > **Note**: A significant amount of memory is required for zlib decompression and especially for compression. These libraries may not work on all microcontrollers because of memory constraints. -## class URL and class URLSearchParams -The `URL` and `URLSearchParams` classes provide utilities for working with URLs and their search parameters. +## class URL and class URLSearchParams +The `URL` and `URLSearchParams` classes provide utilities for working with URLs and their search parameters. ```js import URL from "url"; diff --git a/documentation/devices/esp32.md b/documentation/devices/esp32.md index f3fdf72eb0..9ba4072cbd 100644 --- a/documentation/devices/esp32.md +++ b/documentation/devices/esp32.md @@ -159,7 +159,7 @@ The target ESP32 subclass for a build is specified using the `ESP32_SUBCLASS` pr "build":{ "ESP32_SUBCLASS": "esp32s2" }, -``` +``` | `ESP32_SUBCLASS` | Device | |:---:|:---:| diff --git a/documentation/devices/esp8266.md b/documentation/devices/esp8266.md index b2dc0a978f..638aba73ef 100644 --- a/documentation/devices/esp8266.md +++ b/documentation/devices/esp8266.md @@ -7,7 +7,7 @@ This document provides a guide to building apps for the [ESP8266](https://www.es ## Table of Contents * [Overview](#overview) -* [Platforms](#platforms) +* [Platforms](#platforms) * Setup instructions | [![Apple logo](./../assets/moddable/mac-logo.png)](#mac) | [![Windows logo](./../assets/moddable/win-logo.png)](#win) | [![Linux logo](./../assets/moddable/lin-logo.png)](#lin) | @@ -59,7 +59,7 @@ The Moddable SDK supports many devices built on ESP8266. The following table lis We have also used many displays with the ESP8266 Node MCU board. The following table links to wiring guides and provides corresponding platform identifiers. -| Wiring guide | Platform identifier | +| Wiring guide | Platform identifier | | :--- | :--- | | [Adafruit OLED](./../displays/wiring-guide-adafruit-OLED.md) | `esp/adafruit_oled` | | [Adafruit ST7735](./../displays/wiring-guide-adafruit-1.8-st7735.md) | `esp/adafruit_st7735` | @@ -73,7 +73,7 @@ We have also used many displays with the ESP8266 Node MCU board. The following t ## macOS -The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and ESP8266_RTOS_SDK v3.2. +The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and ESP8266_RTOS_SDK v3.2. ### Installing @@ -82,13 +82,13 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and 2. Create an `esp` directory in your home directory at `~/esp` for required third party SDKs and tools. -3. If you are running macOS 10.15 (Catalina) or earlier, download and install the Silicon Labs [CP210x USB to UART VCP driver](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers). +3. If you are running macOS 10.15 (Catalina) or earlier, download and install the Silicon Labs [CP210x USB to UART VCP driver](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers). If you run macOS Catalina, an extra step is required to enable the VCP driver. If you see a popup that says "System Extension Blocked" during installation, follow the instructions in the dialog to enable the extension in Security & Privacy System Preferences. - + If you are using macOS 10.16 (Big Sur) or later, you do not need to install the VCP driver. -4. If you use macOS Catalina (version 10.15) or later, add an exemption to allow Terminal (or your alternate terminal application of choice) to run software locally that does not meet the system's security policy. Without this setting, the precompiled Xtensa toolchain you will download in the next step will not be permitted to run. +4. If you use macOS Catalina (version 10.15) or later, add an exemption to allow Terminal (or your alternate terminal application of choice) to run software locally that does not meet the system's security policy. Without this setting, the precompiled Xtensa toolchain you will download in the next step will not be permitted to run. To set the security policy exemption for Terminal, go into the Security & Privacy System Preferences, select the Privacy tab, choose Developer Tools from the list on the left, and then tick the checkbox for Terminal or the alternate terminal application from which you will be building Moddable SDK apps. The end result should look like this: @@ -111,7 +111,7 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and cd ESP8266_RTOS_SDK git checkout release/v3.2 ``` - + 8. Install Python and the required Python packages. We've used [brew](https://brew.sh/) and [pip](https://pypi.org/project/pip/) to install the additional components: ```text @@ -119,7 +119,7 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and sudo easy_install pip pip install --user pyserial ``` - + 9. Connect the ESP8266 to your computer with a USB cable. 10. Verify the setup by building `helloworld` for your device target: @@ -146,8 +146,8 @@ error: cannot access /dev/usbserial-0001 ``` There are a few reasons this can happen: - -1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. + +1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. 2. You have a USB cable that is power only. Make sure you're using a data sync-capable USB cable. 3. The computer does not recognize your device. To fix this problem, follow the instructions below. @@ -160,7 +160,7 @@ ls /dev/cu* Then plug in the device and repeat the same command. If nothing new appears in the terminal output, the device isn't being recognized by your computer. -If you are running macOS 10.15 or earlier, make sure you have the correct VCP driver installed. If you are running macOS 10.16 or earlier, you do not need to install the VCP driver. +If you are running macOS 10.15 or earlier, make sure you have the correct VCP driver installed. If you are running macOS 10.16 or earlier, you do not need to install the VCP driver. If it is recognized, you now have the device name and you need to edit the `UPLOAD_PORT` environment variable. Enter the following command, replacing `/dev/cu.SLAB_USBtoUART` with the name of the device on your system. @@ -168,7 +168,7 @@ If it is recognized, you now have the device name and you need to edit the `UPLO export UPLOAD_PORT=/dev/cu.SLAB_USBtoUART ``` - + ### Updating To ensure that your build environment is up to date, perform the following steps: @@ -199,10 +199,10 @@ To ensure that your build environment is up to date, perform the following steps mcconfig -d -m -p esp/ ``` - + ## Windows -The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and `ESP8266_RTOS_SDK v3.2`. +The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and `ESP8266_RTOS_SDK v3.2`. ### Installing @@ -211,13 +211,13 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and 2. Create an `esp` directory in your home `%USERPROFILE%` directory, e.g. `C:\Users\`. - -3. Download and install the Silicon Labs [CP210x USB to UART VCP driver](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers). The driver zip file contains x64 and x86 versions of the installer. Most modern PCs run 64-bit Windows and should use the x64 version of the VCP driver. If you run a 32-bit version of Windows, use the x86 version of the driver. (You can determine if your computer is running a 64-bit version of Windows by checking "About your PC" in System Settings.) + +3. Download and install the Silicon Labs [CP210x USB to UART VCP driver](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers). The driver zip file contains x64 and x86 versions of the installer. Most modern PCs run 64-bit Windows and should use the x64 version of the VCP driver. If you run a 32-bit version of Windows, use the x86 version of the driver. (You can determine if your computer is running a 64-bit version of Windows by checking "About your PC" in System Settings.) 4. Download the [esptool](https://github.com/igrr/esptool-ck/releases/download/0.4.13/esptool-0.4.13-win32.zip). Unzip the archive and copy the `esptool.exe` executable from the `esptool-0.4.13-win32` directory into the `esp` directory. 5. Download and unzip the [Cygwin toolchain support package](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/cygwin.win32.zip). Copy the `cygwin` directory into the `esp` directory. - + 6. Download and unzip the [Xtensa lx106 architecture GCC toolchain](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/esp8266.toolchain.win32.zip). Copy the `xtensa-lx106-elf` directory into the `esp` directory. 7. Download the [ESP8266 core for Arduino repository](https://github.com/esp8266/Arduino/releases/download/2.3.0/esp8266-2.3.0.zip). Copy the extracted `esp8266-2.3.0` folder into your `esp` directory. @@ -244,20 +244,20 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and - Variable value (add to the existing list): `C:\Python27` - Variable value (add to the existing list): `C:\Python27\Scripts` - > Note: You will need to add additional environment variables in a later step, after installing pyserial. But be sure to hit `OK` on the Environment Variables dialog and apply your changes here before continuing. + > Note: You will need to add additional environment variables in a later step, after installing pyserial. But be sure to hit `OK` on the Environment Variables dialog and apply your changes here before continuing. 11. Open a "Command Prompt" window and install the `pyserial` Python Serial Port Extension: ```text pip install pyserial ``` - + 12. Connect the ESP8266 to your computer with a USB cable. 13. Launch the Windows Device Manager, open the "Ports (COM & LPT)" section, and verify the "Silicon Labs CP210x USB to UART Bridge" is displayed. Note the COM port (e.g. COM3) for the next step. > The Device Manager interface may vary depending on the Windows OS version. - + 14. Open the "Environment Variables" dialog of the Control Panel app by following [these instructions](https://www.architectryan.com/2018/08/31/how-to-change-environment-variables-on-windows-10/). From that dialog: - Create a User Variable called `BASE_DIR` and set it to `%USERPROFILE% - Variable name: `BASE_DIR` @@ -275,7 +275,7 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and cd %MODDABLE%\examples\helloworld mcconfig -d -m -p esp/ ``` - + ### Troubleshooting @@ -293,8 +293,8 @@ error: cannot access /dev/usbserial-0001 ``` There are a few reasons this can happen: - -1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. + +1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. 2. You have a USB cable that is power only. Make sure you're using a data sync-capable USB cable. 3. The computer does not recognize your device. To fix this problem, follow the instructions below. @@ -306,7 +306,7 @@ If your device shows up on a COM port other than COM3, you need to edit the `UPL set UPLOAD_PORT=COM3 ``` - + ### Updating To ensure that your build environment is up to date, perform the following steps: @@ -340,7 +340,7 @@ To ensure that your build environment is up to date, perform the following steps ## Linux -The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and ESP8266_RTOS_SDK v3.2. +The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and ESP8266_RTOS_SDK v3.2. ### Installing @@ -349,7 +349,7 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and 2. Create an `esp` directory in your home directory at `~/esp` for required third party SDKs and tools. - + 3. Download and untar the [Xtensa lx106 architecture GCC toolchain](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/esp8266.toolchain.linux.tgz). Copy the `toolchain` directory into the `~/esp` directory. 4. Download the [ESP8266 core for Arduino repository](https://github.com/esp8266/Arduino/releases/download/2.3.0/esp8266-2.3.0.zip). Copy the extracted `esp8266-2.3.0` folder into your `~/esp` directory. @@ -383,7 +383,7 @@ The Moddable SDK build for ESP8266 currently uses ESP8266 Arduino Core 2.3.0 and sudo easy_install pip pip install --user pyserial ``` - + 7. Connect the ESP8266 to your computer with a USB cable. 8. Verify the setup by building `helloworld` for your device target: @@ -405,7 +405,7 @@ For other issues that are common on macOS, Windows, and Linux, see the [Troubles The ESP8266 communicates with the Linux host via the ttyUSB0 device. On Ubuntu Linux the ttyUSB0 device is owned by the `dialout` group. If you get a **permission denied error** when flashing the ESP8266, add your user to the `dialout` group: ```text -sudo adduser dialout +sudo adduser dialout sudo reboot ``` @@ -419,8 +419,8 @@ error: cannot access /dev/usbserial-0001 ``` There are a few reasons this can happen: - -1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. + +1. Your device is not plugged into your computer. Make sure it's plugged in when you run the build commands. 2. You have a USB cable that is power only. Make sure you're using a data sync-capable USB cable. 3. The computer does not recognize your device. To fix this problem, follow the instructions below. @@ -433,7 +433,7 @@ ls /dev/cu* Then plug in the device and repeat the same command. If nothing new appears in the terminal output, the device isn't being recognized by your computer. -If you are running macOS 10.15 or earlier, make sure you have the correct VCP driver installed. If you are running macOS 10.16 or earlier, you do not need to install the VCP driver. +If you are running macOS 10.15 or earlier, make sure you have the correct VCP driver installed. If you are running macOS 10.16 or earlier, you do not need to install the VCP driver. If it is recognized, you now have the device name and you need to edit the `UPLOAD_PORT` environment variable. Enter the following command, replacing `/dev/cu.SLAB_USBtoUART` with the name of the device on your system. @@ -441,7 +441,7 @@ If it is recognized, you now have the device name and you need to edit the `UPLO export UPLOAD_PORT=/dev/cu.SLAB_USBtoUART ``` - + ### Updating To ensure that your build environment is up to date, perform the following steps: @@ -509,28 +509,28 @@ There are a few reasons the upload may fail partway through: - You have a USB cable that does not support higher baud rates. - You're using a board that requires a lower baud rate than the default baud rate that the Moddable SDK uses. -To solve the last two problems above, you can change to a slower baud rate as follows: +To solve the last two problems above, you can change to a slower baud rate as follows: -1. Open `$MODDABLE/tools/mcconfig/make.esp.mk`. +1. Open `$MODDABLE/tools/mcconfig/make.esp.mk`. 2. Find this line, which sets the upload speed to 921600: - ```text + ```text UPLOAD_SPEED ?= 921600 ``` 3. Set the speed to a smaller number. For example: - ```text + ```text UPLOAD_SPEED ?= 115200 ``` - + ## ESP8266 Arduino version 2.4 The Moddable SDK on ESP8266 is hosted by the [ESP8266 core for Arduino](https://github.com/esp8266/Arduino). The Moddable SDK uses version 2.3. Version 2.4 is supported as well. At this time, we do not recommend using version 2.4 as it requires more ROM and more RAM without providing significant benefits for most uses of the Moddable SDK. The team responsible for ESP8266 core for Arduino is aware of [these](https://github.com/esp8266/Arduino/issues/3740) [issues](https://github.com/esp8266/Arduino/issues/4089) and actively working to address them. -You can use version 2.4 today if building on macOS or Linux. +You can use version 2.4 today if building on macOS or Linux. - Follow the instructions above, but use the [version 2.4](https://github.com/esp8266/Arduino/releases/download/2.4.0/esp8266-2.4.0.zip) of ESP8266 Core for Arduino. @@ -539,9 +539,9 @@ You can use version 2.4 today if building on macOS or Linux. ```text ESP_SDK_RELEASE ?= esp8266-2.3.0 ``` - + to: - + ```text ESP_SDK_RELEASE ?= esp8266-2.4.0 ``` diff --git a/documentation/devices/gecko/GeckoBuild.md b/documentation/devices/gecko/GeckoBuild.md index 24c1c67296..c773ebaf01 100644 --- a/documentation/devices/gecko/GeckoBuild.md +++ b/documentation/devices/gecko/GeckoBuild.md @@ -78,7 +78,7 @@ gecko | blue | **-p gecko/blue** | Blue Gecko The platform flag is used with `mcconfig`. $ mcconfig -d -m -p gecko/mighty - + If the platform flag specifies a subplatform, then `mcconfig` will load the build rules from `$MODDABLE/tools/mcconfig/`*platform*`/mk.`*subplatform*`.mk`. In the `manifest.json` file, the `platforms` section can specify both `platform` and `platform/subplatform` subsections. The items are merged with more specific `platform/subplatform` specifications overriding general `platform` specifications. @@ -94,7 +94,7 @@ To get started, install [Simplicity Studio](https://www.silabs.com/products/deve Plug in your board when launching for the first time so that Simplicity Studio updates with the correct SDKs. Install 32 bit MCU, Flex and Bluetooth. As of this writing, the current versions are: - + Gecko SDK Suite - 2.2.2 32-bit MCU SDK - 5.4.0.0 Flex SDK - 2.2.2.1 @@ -125,7 +125,7 @@ Blue Gecko | `soc-ibeacon`, `soc-thermometer` Build, install and run the sample to become familiar with the process. > Note: It is necessary to start with an example project with your board connected so that Simplicity Studio will populate the build rules for the project with the appropriate values for your device. -> +> > Also note: There are many variants of a family of devices. Please note the board (4) and part (2). @@ -152,11 +152,11 @@ Use `mcconfig` to build the moddable library and application for your Gecko sub- $ cd $(MODDABLE)/examples/helloworld $ mcconfig -d -m -p gecko/mighty - + Note: the `-d` option to mcconfig builds the debug version. **helloworld** uses the debugger to display its output. See the **Debugging** section below for instructions on connecting to xsbug. - + #### Modifications to the Simplicity Studio project for the Moddable sdk. @@ -175,7 +175,7 @@ Open the properties window for the project and select *C/C++ Build->Settings*. It is located in $MODDABLE/build/bin/gecko/_platform_/debug/_application_/xs_gecko.a > You will need to change this file path to match the application you are building. - + You may also need to add the `math` library: Open the properties window for the project and select *C/C++ Build->Settings*. @@ -195,7 +195,7 @@ In the Simplicity Studio sample app's **main.c**, add a few things: int gResetCause = 0; uint32_t gWakeupPin = 0; - + void assertEFM() { } // maybe void assertEFM(const char *file, int line) {} depending on your SDK @@ -323,7 +323,7 @@ By default, Moddable uses Sleep level EM3 while waiting. Certain Gecko interface #### EM4 Sleep -Gecko devices also have a deep sleep level EM4. At this level, the device is almost entirely shut off, including RAM, peripherals and most clocks. While in this state, the device can be awoken by a signal on an external GPIO pin or a timer expiration using a low power clock. When awoken, the device reboots. +Gecko devices also have a deep sleep level EM4. At this level, the device is almost entirely shut off, including RAM, peripherals and most clocks. While in this state, the device can be awoken by a signal on an external GPIO pin or a timer expiration using a low power clock. When awoken, the device reboots. During EM4 sleep, a small amount of memory can be kept active at the expense of a slightly increased power draw. The GPIO state can also be retained. @@ -392,7 +392,7 @@ Sleep.WatchdogReset = 0b01000000; // watchdog timer expired During EM4 sleep, RAM is shut off. A small amount of memory persists, and is available for retreival after wakeup. let index; - + index = Sleep.getPersistentValue(0); Sleep.setPersistentValue(0, ++index); @@ -441,7 +441,7 @@ Gecko devices have a number of analog inputs and can be configured to use variou "$(BUILD)/devices/gecko/analog/*", ], }, - + **interface** specifies which ADC interface to use. @@ -486,7 +486,7 @@ The `manifest.json` file contains defines for the base SPI pins "dc": { "pin": 6, "port": "gpioPortB", }, } }, - + This section of the `manifest.json` defines the **SPI** pins, ports, and locations, and which interface to use. The **interface** definition specifies which USART interface to use. @@ -510,7 +510,7 @@ Gecko devices have a number of I2C interfaces. "sda": { "pin": 11, "port": "gpioPortC", "location": 16 }, "scl": { "pin": 10, "port": "gpioPortC", "location": 14 }, }, - + The **interface** definition specifies which I2C interface to use. In this example, **I2C0** is used. The pin PC11 is the SDA pin for I2C0 at location 16 (I2C0_SDA#16). The pin PC10 is the SCL pin for I2C0 at location 14. @@ -555,14 +555,14 @@ The Moddable SDK includes Bluetooth Low Energy (BLE) protocol support for Blue G - During the final link, if Simplicity Studio does not find the Cryotimer routines or defines, copy the code and header files to your project. `em_cryotimer.h` is located in: `/Applications/Simplicity Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite/v2.2/platform/emlib/inc/em_cryotimer.h` - + `em_cryotimer.c` is located in: `/Applications/Simplicity Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite/v2.2/platform/emlib/src/em_cryotimer.c` - During the final link, if Simplicity Studio does not find the `xs_gecko.a` file, either the library path is incorrect, or you have not built the `xs_gecko.a` file with **mcconfig**. $ cd .../application_path $ mcconfig -d -m -p gecko/mighty - + - Unexplainable crashes can occur if Stack or Heap space run out: Depending on the processor and project configuration, you may need to adjust the stack size and heap size of the project. @@ -578,7 +578,7 @@ You can increase that by changing the Radio Profile. When starting a new radio p ![ISC Custom Settings](assets/ISC-RadioConfig.png) -Scroll down to **Profile options->Packet** and select the **Frame Fixed Length** tab. +Scroll down to **Profile options->Packet** and select the **Frame Fixed Length** tab. ![Frame Fixed Length](assets/FrameLength.png) @@ -736,13 +736,13 @@ base/sleep | sleep | x | x | x network/ble/* | BLE | | | | x drivers/TMP102 | I2C | x | x | drivers/HMC5883L | I2C | x | x | -drivers/ls013b4dn04 | Sharp Memory Display | x | x | x -pins/monitor | GPIO Interrupt | | x | -pins/simpleAnalog | analog | | x | +drivers/ls013b4dn04 | Sharp Memory Display | x | x | x +pins/monitor | GPIO Interrupt | | x | +pins/simpleAnalog | analog | | x | piu/balls | SPI / ili9341 | x | x | piu/transitions | SPI / ili9341 | x | x | piu/cards | SPI / ili9341 | x | x | piu/love-e-ink | SPI / destm32s | x | x | drivers/radio/radiotest | radio | | x | - + diff --git a/documentation/devices/m5core_ink.md b/documentation/devices/m5core_ink.md index 3acb2258e6..f27f40cad2 100644 --- a/documentation/devices/m5core_ink.md +++ b/documentation/devices/m5core_ink.md @@ -13,7 +13,7 @@ This document provides information about using the M5Core Ink with the Moddable - [Troubleshooting](#troubleshooting) - [Development Resources](#development-resources) - [Port Status](#port-status) - - [Display Driver](#display-driver) + - [Display Driver](#display-driver) - [Buttons](#buttons) - [LED](#led) - [Buzzer](#buzzer) @@ -44,15 +44,15 @@ After you've set up your host environment and ESP32 tools, take the following st 2. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp32/m5core_ink` with `mcconfig` to build for M5Core Ink. For example, to build the [`epaper-photos` example](../../examples/piu/epaper-photos): - + ```text cd $MODDABLE/examples/piu/epaper-photos mcconfig -d -m -p esp32/m5core_ink ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. @@ -70,7 +70,7 @@ The following are implemented and working: - EPD display driver (GDEW0154M09) - RTC (PCF8563 / BM8563) -- Up / Down / Middle / Power / External buttons +- Up / Down / Middle / Power / External buttons - LED - Buzzer - Battery voltage @@ -80,7 +80,7 @@ The following are implemented and working: The display driver is a [Poco `PixelsOut`](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/commodetto/commodetto.md#pixelsout-class) implementation. This allows it to use both the [Poco](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/commodetto/poco.md) graphics APIs and[ Piu](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/piu/piu.md) user interface framework from the Moddable SDK. -The display driver is written entirely in JavaScript. It uses [Ecma-419 IO](https://419.ecma-international.org/#-9-io-class-pattern) APIs for all hardware access. Performance is excellent, often faster than the EPD class built into the native M5Core Ink library. +The display driver is written entirely in JavaScript. It uses [Ecma-419 IO](https://419.ecma-international.org/#-9-io-class-pattern) APIs for all hardware access. Performance is excellent, often faster than the EPD class built into the native M5Core Ink library. The display driver implements dithering, which allows many levels of gray to be displayed using only black and white pixels. The default dithering algorithm is the venerable [Atkinson dither](https://twitter.com/phoddie/status/1274054345969950720). To change to Burkes or to disable dithering: @@ -101,7 +101,7 @@ The display driver does a full screen refresh on the first draw after instantiat screen.configure({refresh: false}); ``` -The display driver uses partial updates after the first frame. To force a full screen update: +The display driver uses partial updates after the first frame. To force a full screen update: ```js screen.configure({refresh: true}); @@ -220,7 +220,7 @@ power.main.write(0); ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on M5Core Ink. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on M5Core Ink. That said, not every example is compatible with M5Core Ink hardware. For example, some examples are designed to test specific display and touch drivers that are not compatible with the M5Core Ink display and give a build error. @@ -231,7 +231,7 @@ There are several example applications in the Moddable SDK that show how to take ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. diff --git a/documentation/devices/m5paper.md b/documentation/devices/m5paper.md index a114939ed9..e8c262e35c 100644 --- a/documentation/devices/m5paper.md +++ b/documentation/devices/m5paper.md @@ -1,4 +1,4 @@ -# M5Paper Developer Guide +# M5Paper Developer Guide Copyright 2021-2022 Moddable Tech, Inc.
Revised: March 22, 2022 @@ -13,7 +13,7 @@ This document provides information about using the M5Paper with the Moddable SDK - [Troubleshooting](#troubleshooting) - [Development Resources](#development-resources) - [Port Status](#port-status) - - [Display Driver](#display-driver) + - [Display Driver](#display-driver) - [Update Modes](#update-modes) - [Image Filters](#image-filters) - [Examples](#examples) @@ -50,19 +50,19 @@ After you've set up your host environment and ESP32 tools, take the following st 2. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp32/m5paper` with `mcconfig` to build for M5Paper. For example, to build the [`epaper-photos` example](../../examples/piu/epaper-photos): - + ```text cd $MODDABLE/examples/piu/epaper-photos mcconfig -d -m -p esp32/m5paper ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. Use the platform `-p simulator/m5paper` with `mcconfig` to build for the M5Paper simulator. - + ## Troubleshooting @@ -79,7 +79,7 @@ The following are implemented and working: - EPD display driver - GT911 touch driver - SHT30 temperature/humidity sensor -- A / B / C buttons +- A / B / C buttons - RTC > **Note**: The I2C address of the GT911 touch controller floats. The implementation tries both addresses 0x14 and 0x5D. This is handled in host provider's Touch constructor -- not in driver and not in user script. If 0x14 fails, an exception is thrown before it retries at 0x5D. If you encounter this, just hit Go in xsbug. @@ -154,7 +154,7 @@ screen.config({filter}); ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on M5Paper. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on M5Paper. That said, not every example is compatible with M5Paper hardware. For example, some examples are designed to test specific display and touch drivers that are not compatible with the M5Paper display and give a build error. @@ -163,7 +163,7 @@ There are several example applications in the Moddable SDK that show how to take ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. diff --git a/documentation/devices/moddable-four.md b/documentation/devices/moddable-four.md index 88127a02d1..2847f1fe02 100644 --- a/documentation/devices/moddable-four.md +++ b/documentation/devices/moddable-four.md @@ -41,9 +41,9 @@ It also includes an integrated LIS3DH accelerometer, jog dial, and CR2032 batter -**Note:** LCD-PWR / GPIO23 is not for use as a general GPIO. It is used to provide power to a sensor and to the screen. +**Note:** LCD-PWR / GPIO23 is not for use as a general GPIO. It is used to provide power to a sensor and to the screen. -- Writing `0` to GPIO23 emits 3.3V on LCD-PWR, which also gives power to the screen. +- Writing `0` to GPIO23 emits 3.3V on LCD-PWR, which also gives power to the screen. - Writing `1` to GPIO23 turns off the the pin and the screen. @@ -112,17 +112,17 @@ After you've setup your environment and nRF5 tools, take the following steps to 3. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p nrf52/moddable_four` with `mcconfig` to build for Moddable Four. Build the [`piu/balls`](../../examples/piu/balls) example: - + ```text cd $MODDABLE/examples/piu/balls mcconfig -d -m -p nrf52/moddable_four ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation and more. - + Use the platform -p `sim/moddable_four` with `mcconfig` to build for the Moddable Four simulator. @@ -167,7 +167,7 @@ new Host.JogDial({ } }); ``` - + #### Display Power To use the Moddable Four display, the LCD power pin must be enabled. In the `moddable_four/setup-target.js` file, the screen is enabled if the `autobacklight` config variable is set: @@ -230,7 +230,7 @@ There are many energy management APIs available on Moddable Four. These include: should have a readme.md in that directory which describes the examples --> -See the [nRF52 Low Power Notes](./nRF52-low-power.md) for details. Examples of different sleep and wakeup modes can be found in `$MODDABLE/build/devices/nrf52/examples/sleep`. +See the [nRF52 Low Power Notes](./nRF52-low-power.md) for details. Examples of different sleep and wakeup modes can be found in `$MODDABLE/build/devices/nrf52/examples/sleep`. ## Troubleshooting @@ -264,7 +264,7 @@ The Moddable Four simulator renders images in 8-bit grayscale, which matches how ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on Moddable Four. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Many of these examples run on Moddable Four. Many of the examples that use Commodetto and Piu are designed for colored QVGA screens. While they will run on Moddable Four, the colors will be dithered when rendered and some screens may be cropped. Not every example is compatible with Moddable Four hardware. Some examples are designed to test specific display and touch drivers that are not compatible with the Moddable Four display and give a build error. @@ -273,7 +273,7 @@ Many of the examples that use Commodetto and Piu are designed for colored QVGA s Documentation for the nRF5 device and SDK can be found on the [Nordic Semiconductor Infocenter](https://infocenter.nordicsemi.com/topic/struct_nrf52/struct/nrf52840.html). Of particular interest is the documentation for the Nordic nRF5 SDK v17.0.2, which is available [here](https://infocenter.nordicsemi.com/topic/struct_sdk/struct/sdk_nrf5_latest.html). -Documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +Documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - [Using the Moddable SDK with nRF52](./nrf52.md) explains how to get set-up for development, supported devices, and more. - [nRF52 Low Power Notes](./nRF52-low-power.md) describes the techniques and APIs to maximize battery life by minimizing power consumption. diff --git a/documentation/devices/moddable-one.md b/documentation/devices/moddable-one.md index 739053b38a..5ff70106ca 100644 --- a/documentation/devices/moddable-one.md +++ b/documentation/devices/moddable-one.md @@ -65,7 +65,7 @@ After you've set up your host environment and ESP8266 tools, take the following 1. Attach the programmer to your Moddable One. Make sure you have the programmer oriented correctly. The orientation should match the image below. - + **Note**: The USB port on Moddable One may be used to provide power when operating without the programmer. The USB port is only for powering Moddable One. It cannot be used to program Moddable One. @@ -76,15 +76,15 @@ After you've set up your host environment and ESP8266 tools, take the following 3. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp/moddable_one` with `mcconfig` to build for Moddable One. For example, to build the [`piu/balls` example](../../examples/piu/balls): - + ```text cd $MODDABLE/examples/piu/balls mcconfig -d -m -p esp/moddable_one ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. Use the platform `-p simulator/moddable_one` with `mcconfig` to build for the Moddable One simulator. @@ -101,14 +101,14 @@ See the Troubleshooting section of the [ESP8266 documentation](./esp8266.md) for ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable One. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable One. That said, not every example is compatible with Moddable One hardware. For example, the ESP8266 does not have BLE capabilities so BLE examples do not build or run. Some examples are designed to test specific display and touch drivers that are not compatible with the Moddable One display and give a build error. ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. diff --git a/documentation/devices/moddable-three.md b/documentation/devices/moddable-three.md index df29453926..6c6baff525 100644 --- a/documentation/devices/moddable-three.md +++ b/documentation/devices/moddable-three.md @@ -55,15 +55,15 @@ After you've set up your host environment and ESP8266 tools, take the following 3. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp/moddable_three` with `mcconfig` to build for Moddable Three. For example, to build the [`piu/love-e-ink` example](../../examples/piu/love-e-ink): - + ```text cd $MODDABLE/examples/piu/love-e-ink mcconfig -d -m -p esp/moddable_three ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. Use the platform `-p simulator/moddable_three` with `mcconfig` to build for the Moddable Three simulator. @@ -79,14 +79,14 @@ See the Troubleshooting section of the [ESP8266 documentation](./esp8266.md) for ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Most of these examples run on Moddable Three. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. Most of these examples run on Moddable Three. That said, many of the examples that use Commodetto and Piu are designed for colored screens with a faster refresh rate. In addition, not every example is compatible with Moddable Three hardware. For example, the ESP8266 does not have BLE capabilities so BLE examples do not build or run. Some examples are designed to test specific display and touch drivers that are not compatible with the Moddable Three display and give a build error. ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. diff --git a/documentation/devices/moddable-two.md b/documentation/devices/moddable-two.md index 4c127120fd..5220271b5d 100644 --- a/documentation/devices/moddable-two.md +++ b/documentation/devices/moddable-two.md @@ -99,7 +99,7 @@ Power can be supplied to the Moddable Two via the following: ### Dimensions -The complete dimensions of Moddable Two are provided in this [PDF document](../assets/devices/moddable-two-dimensions.pdf). These are helpful when designing a case for Moddable Two. +The complete dimensions of Moddable Two are provided in this [PDF document](../assets/devices/moddable-two-dimensions.pdf). These are helpful when designing a case for Moddable Two. ## SDK and Host Environment Setup @@ -118,7 +118,7 @@ After you've set up your host environment and ESP32 tools, take the following st 1. Attach the programmer to your Moddable Two. Make sure you have the programmer oriented correctly. The orientation should match the image below. - + **Note**: The USB port on Moddable Two may be used to provide power when operating without the programmer. The USB port is only for powering Moddable Two. It cannot be used to program Moddable Two. @@ -129,19 +129,19 @@ After you've set up your host environment and ESP32 tools, take the following st 3. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp32/moddable_two` with `mcconfig` to build for Moddable Two. For example, to build the [`piu/balls` example](../../examples/piu/balls): - + ```text cd $MODDABLE/examples/piu/balls mcconfig -d -m -p esp32/moddable_two ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. - + Use the platform `-p simulator/moddable_two` with `mcconfig` to build for the Moddable Two simulator. - + ## Troubleshooting @@ -154,14 +154,14 @@ See the Troubleshooting section of the [ESP32 documentation](./esp32.md) for a l ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable Two. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable Two. That said, not every example is compatible with Moddable Two hardware. For example, some examples are designed to test specific display and touch drivers that are not compatible with the Moddable Two display and give a build error. ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. @@ -170,7 +170,7 @@ All the documentation for the Moddable SDK is in the [documentation](../) direct ### Backlight -The original Moddable Two has an always-on backlight. The second revision has the ability to adjust the backlight brightness in software. Moddable Two units with backlight brightness control are identified by the small `ESP32 r9` printed on the back of the board to the right of the Moddable logo. +The original Moddable Two has an always-on backlight. The second revision has the ability to adjust the backlight brightness in software. Moddable Two units with backlight brightness control are identified by the small `ESP32 r9` printed on the back of the board to the right of the Moddable logo. The backlight control is connected to GPIO 18. There is a constant defined for the backlight GPIO in the host config. diff --git a/documentation/devices/moddable-zero.md b/documentation/devices/moddable-zero.md index 521a013dcd..ba4b5266c1 100644 --- a/documentation/devices/moddable-zero.md +++ b/documentation/devices/moddable-zero.md @@ -55,15 +55,15 @@ After you've set up your host environment, take the following steps to install a 2. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Use the platform `-p esp/moddable_zero` with `mcconfig` to build for Moddable Zero. For example, to build the [`piu/balls` example](../../examples/piu/balls): - + ``` cd $MODDABLE/examples/piu/balls mcconfig -d -m -p esp/moddable_zero ``` - + The [examples readme](../../examples) contains additional information about other commonly used `mcconfig` arguments for screen rotation, Wi-Fi configuration, and more. @@ -77,14 +77,14 @@ See the Troubleshooting section of the [ESP8266 documentation](./esp8266.md) for ### Examples -The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable Zero. +The Moddable SDK has over 150 [example apps](../../examples) that demonstrate how to use its many features. The vast majority of these examples run on Moddable Zero. That said, not every example is compatible with Moddable Zero hardware. For example, the ESP8266 does not have BLE capabilities so BLE examples do not build or run. Some examples are designed to test specific display and touch drivers that are not compatible with the Moddable Zero display and give a build error. ### Documentation -All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: +All the documentation for the Moddable SDK is in the [documentation](../) directory. The **documentation**, **examples**, and **modules** directories share a common structure to make it straightforward to locate information. Some of the highlights include: - The `commodetto` subdirectory, which contains resources related to Commodetto--a bitmap graphics library that provides a 2D graphics API--and Poco, a lightweight rendering engine. - The `piu` subdirectory, which contains resources related to Piu, a user interface framework that makes it easier to create complex, responsive layouts. diff --git a/documentation/devices/nRF52-low-power.md b/documentation/devices/nRF52-low-power.md index 436b147137..39f335a234 100644 --- a/documentation/devices/nRF52-low-power.md +++ b/documentation/devices/nRF52-low-power.md @@ -42,7 +42,7 @@ System OFF power mode is deep sleep. The CPU and most peripherals are asleep and ## FreeRTOS and Low Power Moddable apps run on FreeRTOS on nRF52 devices. To conserve energy, FreeRTOS supports a [Tickless Idle](https://www.freertos.org/low-power-tickless-rtos.html) mode. Tickless idle disables the periodic tick interrupt, allowing the CPU to enter low power mode until a task needs to run or interrupt occurs, at which point the RTOS tick value is adjusted. -The core of the tickless idle implementation/hook is provided by our `vApplicationSleep()` function. This function enters System ON sleep mode when the application is idle and exits System ON sleep mode when an interrupt occurs or a task needs to run. +The core of the tickless idle implementation/hook is provided by our `vApplicationSleep()` function. This function enters System ON sleep mode when the application is idle and exits System ON sleep mode when an interrupt occurs or a task needs to run. The main loop in a Moddable app on nRF52 executes all "ready" timers and then waits on messages until the next timer needs to fire. If no timers are active, the app waits for a maximum delay time. This wait triggers the FreeRTOS scheduler, which in turn calls the tickless idle function and puts the app into System ON sleep mode. @@ -154,7 +154,7 @@ The `powerMode` setter function sets the System ON low power sub-mode. The `Powe ### Properties -| Name | Description | +| Name | Description | | --- | --- | | `ConstantLatency` | Constant Latency sub-mode | | `LowPower` | Low Power sub-mode | @@ -172,7 +172,7 @@ Sleep.powerMode = PowerMode.LowPower; #### `setRetainedValue(index, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `index` | `number` | Index of 32-bit memory slot to retain | `value` | `number` | 32-bit value to retain @@ -186,7 +186,7 @@ import {Sleep} from "sleep"; // retain values for (let index = 0; index < 32; ++index) Sleep.setRetainedValue(index, index + 1); - + // sleep Sleep.deep(); ``` @@ -194,7 +194,7 @@ Sleep.deep(); #### `getRetainedValue(index)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `index` | `number` | Zero-based index of 32-bit memory slot to retrieve. The `getRetainedValue` method allows an application to retrieve a 32-bit memory value previously retained across System OFF sleep. The function returns a `number` containing the retained memory value when available. If no memory was retained the function returns the value `0`. @@ -210,7 +210,7 @@ trace(`Retrieved value ${value} at index ${index}\n`); #### `setup()` -The `setup` method is called internally by the nRF52 [power.js](./../../build/devices/nrf52/setup/power.js) [setup module](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/base/setup.md) to initialize low power features at launch. This method restores the system time after waking up from deep sleep, i.e. after a call to `Sleep.deep` when a milliseconds timeout value is provided. The function also powers down unused RAM for applications that specify a RAM configuration. +The `setup` method is called internally by the nRF52 [power.js](./../../build/devices/nrf52/setup/power.js) [setup module](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/base/setup.md) to initialize low power features at launch. This method restores the system time after waking up from deep sleep, i.e. after a call to `Sleep.deep` when a milliseconds timeout value is provided. The function also powers down unused RAM for applications that specify a RAM configuration. ## Example apps @@ -223,9 +223,9 @@ Example apps are provided to demonstrate the various `Sleep` class features: | [retained-values](./../../build/devices/nrf52/examples/sleep/retained-values) | Retain 32 values across System OFF sleep mode and verify the values on reset. | [wake-on-analog](./../../build/devices/nrf52/examples/sleep/wake-on-analog) | Configure wake-up on analog crossing configurations. | [wake-on-digital](./../../build/devices/nrf52/examples/sleep/wake-on-digital) | Configure wake-up on a button press. -| [wake-on-motion](./../../build/devices/nrf52/examples/sleep/wake-on-motion) | Configure wake-up from a connected LIS3DH accelerometer configured to generate interrupts on motion. -| [wake-on-multiple](./../../build/devices/nrf52/examples/sleep/wake-on-multiple) | Configure wake-up from a combination of analog and digital triggers. -| [wake-on-timer](./../../build/devices/nrf52/examples/sleep/wake-on-timer) | Configure wake-up after the specified number of milliseconds have passed. +| [wake-on-motion](./../../build/devices/nrf52/examples/sleep/wake-on-motion) | Configure wake-up from a connected LIS3DH accelerometer configured to generate interrupts on motion. +| [wake-on-multiple](./../../build/devices/nrf52/examples/sleep/wake-on-multiple) | Configure wake-up from a combination of analog and digital triggers. +| [wake-on-timer](./../../build/devices/nrf52/examples/sleep/wake-on-timer) | Configure wake-up after the specified number of milliseconds have passed. ## Power Consumption on Moddable Four diff --git a/documentation/devices/nrf52.md b/documentation/devices/nrf52.md index a95af47ee3..74110882bf 100644 --- a/documentation/devices/nrf52.md +++ b/documentation/devices/nrf52.md @@ -19,7 +19,7 @@ This document is a guide to building apps for the nRF52840 SoC from Nordic using | [![Apple logo](./../assets/moddable/mac-logo.png)](#mac) | [![Windows logo](./../assets/moddable/win-logo.png)](#win) | [![Linux logo](./../assets/moddable/lin-logo.png)](#lin) | | :--- | :--- | :--- | | • [Installing](#mac-instructions)
• [Troubleshooting](#mac-troubleshooting) | • [Installing](#win-instructions)
• [Troubleshooting](#win-troubleshooting) | • [Installing](#lin-instructions)
• [Troubleshooting](#lin-troubleshooting) - + * [Troubleshooting](#troubleshooting) * [Debugging Native Code](#debugging-native-code) * [Bootloader](#bootloader) @@ -73,7 +73,7 @@ nRF52840 has the following features: ## Build Types The nRF52 supports three kinds of builds: debug, instrumented, and release. Each is appropriate for different stages in the product development process. You select which kind of build you want from the command line when running `mcconfig`. - + ### Debug A debug build is used for debugging JavaScript. In a debug build, the device will attempt to connect to xsbug at startup over USB or serial depending on the device configuration. Symbols will be included for native gdb debugging. @@ -124,7 +124,7 @@ The Moddable SDK build for nRF52 currently uses Nordic nRF5 SDK v17.0.2. 6. Moddable Four uses a modified [Adafruit nRF52 Bootloader](https://github.com/Moddable-OpenSource/Adafruit_nRF52_Bootloader) that supports the UF2 file format for flashing firmware to a device. Moddable uses the `uf2conv.py` Python tool from Microsoft that packages the UF2 binary for transfer to the device. Download the [uf2conv](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/uf2conv.py) tool. Move or copy the `uf2conv.py` file into the `nrf5` directory. Use `chmod` to change the access permissions of `uf2conv` to make it executable. - + ```text cd ~/nrf5 chmod 755 uf2conv.py @@ -392,15 +392,15 @@ GDB communicates with the nRF58240 device via a J-Link connection in the nRF5284 ```text arm-none-eabi-gdb $MODDABLE/build/tmp/nrf52/moddable_four/debug/heart-rate-server/xs_nrf52.out -x ~/nrf5/gdb_cmds.txt ``` - + The GDB server connects with the client, downloads the application and stops at the breakpoint `main` specified in the GDB setup command file: ```text Breakpoint 1 at 0x46550: file /Users//Projects/moddable/build/devices/nrf52/xsProj/main.c, line 149. Resets core & peripherals via SYSRESETREQ & VECTRESET bit. - + Breakpoint 1, main () at /Users//Projects/moddable/build/devices/nrf52/xsProj/main.c:149 - + 149 clock_init(); (gdb) ``` @@ -433,23 +433,23 @@ To use a nRF52840 device with the Moddable SDK, you will have to install the boo You will need a Segger J-Link or equivalent to program the bootloader. -1. Connect your device to the J-Link in the same way that you would for the debugger. See the +1. Connect your device to the J-Link in the same way that you would for the debugger. See the [Debugging Native Code](#debugging-native-code) section. 2. Fetch the bootloader repository: - + ``` git clone https://github.com/Moddable-OpenSource/Adafruit_nRF52_Bootloader --recurse-submodules ``` 3. Build for your device - + ``` cd Adafuit_nRF52_Bootloader make BOARD=moddable_four ``` - + > Note: The following BOARD configurations have been updated to support Moddable. - `moddable_four` - `moddable_itsybitsy_nrf52` @@ -457,10 +457,10 @@ section. - `moddable_pca10056` - `moddable_sparkfun52840` - `moddable_xiao` - + 4. Install to your device. First install the SoftDevice, then flash the bootloader: - + ``` make BOARD=moddable_four sd make BOARD=moddable_four flash @@ -472,19 +472,19 @@ You can now program the device. ---- - + -## nRF5 SDK Modifications +## nRF5 SDK Modifications Moddable Four requires a few small adjustments to the Nordic nRF5 SDK. You can use the prepared SDK at [Nordic nRF5 SDK](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/nRF5_SDK_17.0.2_d674dde-mod.zip). Or you can make your own by following these steps to modify the SDK: -1. Download the [Nordic nRF5 SDK](https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK/Download) by taking the following steps: +1. Download the [Nordic nRF5 SDK](https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK/Download) by taking the following steps: - Select `v17.0.2` from the nRF5 SDK versions section. - - ![](../assets/devices/nrf5-sdk-versions.png) + + ![](../assets/devices/nrf5-sdk-versions.png) - Uncheck all SoftDevices. diff --git a/documentation/devices/pico.md b/documentation/devices/pico.md index ee02886131..4dfc280d51 100644 --- a/documentation/devices/pico.md +++ b/documentation/devices/pico.md @@ -5,7 +5,7 @@ Revised: May 30, 2023 This document describes how to start building Moddable applications for the Raspberry Pi Pico. It provides information on how to configure host build environments, how to build and deploy apps, and includes links to external development resources. > Note: The Pico port is solid and mostly complete. Possible future work includes: -> +> > - Mods > - JavaScript Atomics > - Web Workers making use of the second core @@ -139,12 +139,12 @@ The Moddable SDK supports devices built with the Pico. The following table lists cd $HOME/pico git clone -b sdk-1.5.0 https://github.com/raspberrypi/pico-extras ``` - + ```text cd $HOME/pico git clone -b sdk-1.5.0 https://github.com/raspberrypi/pico-examples ``` - + 6. Set the `PICO_SDK_DIR` environment variable to point to the Pico SDK directory: ```text @@ -169,10 +169,10 @@ After you've setup your macOS host environment, take the following steps to inst 1. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Specify the platform `-p pico` with `mcconfig` to build for the Pico. Build the [`helloworld`](../../examples/helloworld) example: - + ```text cd $MODDABLE/examples/helloworld mcconfig -d -m -p pico @@ -181,7 +181,7 @@ After you've setup your macOS host environment, take the following steps to inst The app will be built and installed. `xsbug` will be launched and connected to the Pico after a few seconds. > Note: If the device is unresponsive, you may see this message: -> +> > ```text > Hold the BOOTSEL button and power-cycle the device. > Waiting for /Volumes/RPI-RPI2..... @@ -195,7 +195,7 @@ The app will be built and installed. `xsbug` will be launched and connected to t ### Troubleshooting - If the macOS **DISK NOT EJECTED PROPERLY** remain on your screen, you can download and use the [`ejectfix.py`](https://github.com/Moddable-OpenSource/tools/releases/download/v1.0.0/ejectfix.py) tool to make them auto-dismiss. - + See the [article at the Adafruit blog](https://blog.adafruit.com/2021/05/11/how-to-tone-down-macos-big-surs-circuitpy-eject-notifications/) for details. @@ -256,12 +256,12 @@ Not yet available. cd $HOME/pico git clone -b sdk-1.5.0 https://github.com/raspberrypi/pico-extras ``` - + ```text cd $HOME/pico git clone -b sdk-1.5.0 https://github.com/raspberrypi/pico-examples ``` - + 6. Set the `PICO_SDK_DIR` environment variable to point to the Pico SDK directory: ```text @@ -291,19 +291,19 @@ After you've setup your Linux host environment, take the following steps to inst > Note: a USB hub with power switch is very helpful here. You will know that programming mode is active when a disk named `RPI-RP2` appears on your desktop. - + > Note: For best results with a virtual machine, capture the Pico device in both the Boot mode state and running state. The image below shows the configuration in VirtualBox: - + 3. Build and deploy the app with `mcconfig`. - `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). - + `mcconfig` is the command line tool to build and launch Moddable apps on microcontrollers and the simulator. Full documentation of `mcconfig` is available [here](../tools/tools.md). + Specify the platform `-p pico` with `mcconfig` to build for the Pico. Build the [`helloworld`](../../examples/helloworld) example: - + ```text cd $MODDABLE/examples/helloworld mcconfig -d -m -p pico @@ -316,7 +316,7 @@ The app will be built and installed. `xsbug` will be launched and connected to t ## Debugging Native Code -Refer to the [Getting Started With Pico][picogettingstarteddoc] for +Refer to the [Getting Started With Pico][picogettingstarteddoc] for instructions on setting up your hardware. These instructions have been tested on a macOS host using the two Pico SWD setup described in Appendix A: Using Picoprobe. @@ -345,7 +345,7 @@ These instructions have been tested on a macOS host using the two Pico SWD setup (gdb) monitor reset init (gdb) continue ``` - + ## Reference Documents @@ -354,7 +354,7 @@ These instructions have been tested on a macOS host using the two Pico SWD setup [Hardware Design with RP2040][picohwdoc] [Raspberry Pi Pico C SDK][picosdkdoc] - + [picogettingstarteddoc]:https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf [picohwdoc]:https://datasheets.raspberrypi.org/rp2040/hardware-design-with-rp2040.pdf diff --git a/documentation/devices/qca4020/README.md b/documentation/devices/qca4020/README.md index ecc2133aee..12974f5322 100644 --- a/documentation/devices/qca4020/README.md +++ b/documentation/devices/qca4020/README.md @@ -57,7 +57,7 @@ After the initial host setup, there are four major steps to build and deploy a M 3. Flash the application to the board. -4. Use `gdb` to launch and debug the native portion of your application. Use `xsbug` to debug your ECMAScript application. +4. Use `gdb` to launch and debug the native portion of your application. Use `xsbug` to debug your ECMAScript application. ## Getting Started @@ -76,7 +76,7 @@ Decompress the SDK file into a `~/qualcomm` directory making: ```text /home//qualcomm/qca4020 ``` - + The `qca4020` directory should contain a `target/` subdirectory. #### Environment variables @@ -99,7 +99,7 @@ export PATH=$PATH:$SDK/bin/cortex-m4 #### Arm toolchain setup -Download [version 6.2 (Linux, 64-bit)][armtoolslink] of the GNU embedded toolchain for ARM-based processors from the [Arm Developer Site][armdevsite] +Download [version 6.2 (Linux, 64-bit)][armtoolslink] of the GNU embedded toolchain for ARM-based processors from the [Arm Developer Site][armdevsite] Update the `PATH` environment variable to include the toolchain installation path: @@ -128,7 +128,7 @@ git clone https://source.codeaurora.org/external/quartz/ioe/qurt ``` > Note: You may get an warning here. Continue. - + ```text cd qurt git checkout v2.0 @@ -160,7 +160,7 @@ To trigger the `vApplicationStackOverflowHook()` callback in `$MODDABLE/build/de ``` To trigger the `vApplicationMallocFailedHook()` callback when memory allocation fails, change the following config value: - + ```text #define configUSE_MALLOC_FAILED_HOOK 1 ``` @@ -191,7 +191,7 @@ cp output/free_rtos.lib ~/qualcomm/qca4020/target/lib/cortex-m4IPT/freertos/ ###### Ref: [B] Development Kit User Guide - section 3.7.2.1 -[OpenOCD](http://openocd.org) is used to flash the binary to the QCA4020. +[OpenOCD](http://openocd.org) is used to flash the binary to the QCA4020. Download [openocd-0.10.0](https://sourceforge.net/projects/openocd/files/openocd/0.10.0/) and build with the `--enable-ftdi` option. The location doesn't matter. @@ -239,13 +239,13 @@ to: ```text @@ -27,7 +27,7 @@ This document provides instructions to build and run Moddable SDK apps for the W ``` If you already have the Emscripten repository, upgrade to the latest version using the following commands: - + ```text cd ~/Projects/emsdk git pull @@ -36,31 +36,31 @@ This document provides instructions to build and run Moddable SDK apps for the W 2. Make sure you have all of the Emscripten prerequisites listed for your host platform in the **Platform-specific notes** section of the [Emscripten Download and install webpage](https://emscripten.org/docs/getting_started/downloads.html#platform-notes-installation-instructions-sdk). 3. Install and activate the latest version of Emscripten. - + ```text cd ~/Projects/emsdk ./emsdk install latest ./emsdk activate latest ``` - + > We last tested using version 3.1.1 (commit `0f0ea34526515d0b2caa262ab5915bc1a7e5dd71`). - + 4. If you do not already have the [Binaryen](https://github.com/WebAssembly/binaryen) repository, clone the repository into your `~/Projects` directory. ```text cd ~/Projects git clone --recursive https://github.com/WebAssembly/binaryen.git ``` - + If you already have the Binaryen repository, upgrade to the latest version using the following commands: - + ```text cd ~/Projects/binaryen git pull origin main --recurse-submodules ``` - + If you experience any problems updating the Binaryen repository, you can simply delete the binaryen directory and re-clone it instead: - + ```text cd ~/Projects rm -rf binaryen @@ -73,8 +73,8 @@ This document provides instructions to build and run Moddable SDK apps for the W cd ~/Projects/binaryen cmake . && make ``` - - > We last tested using wasm-opt version 105 (commit `060442225165d0423d06ea33ab865e850b54f61b`) + + > We last tested using wasm-opt version 105 (commit `060442225165d0423d06ea33ab865e850b54f61b`) 6. Setup the `PATH` and other environment variables by pasting the following commands into your `~/.profile`. The first command sources a shell script that sets environment variables for Emscripten. The second updates your `PATH` to include BinaryEn. ```text @@ -92,32 +92,32 @@ This document provides instructions to build and run Moddable SDK apps for the W cd ${MODDABLE}/build/makefiles/wasm make ``` - + 8. To test, build the `balls` example for the `wasm` target. ```text cd $MODDABLE/examples/piu/balls mcconfig -d -m -p wasm ``` - + You can run the app that's built in the browser by hosting it on a local HTTP server. Python provides a simple tool for doing this. - + If you are using Python 2: - + ```text cd $MODDABLE/build/bin/wasm/debug/balls python -m SimpleHTTPServer ``` - + If you are using Python 3: - + ```text cd $MODDABLE/build/bin/wasm/debug/balls python3 -m http.server ``` - + Go to [`localhost:8000`](http://localhost:8000) in a browser. You should see a web page with a simulator running `balls`. - + ## Linux @@ -130,7 +130,7 @@ This document provides instructions to build and run Moddable SDK apps for the W ``` If you already have the Emscripten repository, upgrade to the latest version using the following commands: - + ```text cd ~/Projects/emsdk git pull @@ -145,23 +145,23 @@ This document provides instructions to build and run Moddable SDK apps for the W ./emsdk install latest ./emsdk activate latest ``` - + > We last tested using version 3.1.2 (commit `476a14d60d0d25ff5a1bfee18af73a4b9bfbd385`). - + 4. If you do not already have the [Binaryen](https://github.com/WebAssembly/binaryen) repository, clone the repository into your `~/Projects` directory. ```text cd ~/Projects git clone --recursive https://github.com/WebAssembly/binaryen.git ``` - + If you already have the Binaryen repository, upgrade to the latest version using the following commands: - + ```text cd ~/Projects/binaryen git pull origin main --recurse-submodules ``` - + If you experience any problems updating the Binaryen repository, you can simply delete the binaryen directory and re-clone it instead: ```text @@ -171,13 +171,13 @@ This document provides instructions to build and run Moddable SDK apps for the W ``` 5. Build the Binaryen tools. - + ```text cd ~/Projects/binaryen cmake . && make ``` - - > We last tested using wasm-opt version 105 (commit `707be2b55075dccaaf0a70e23352c972fce5aa76`) + + > We last tested using wasm-opt version 105 (commit `707be2b55075dccaaf0a70e23352c972fce5aa76`) 6. Setup the `PATH` and other environment variables by pasting the following commands into your `~/.bashrc`. The first command sources a shell script that sets environment variables for Emscripten. The second updates your `PATH` to include BinaryEn. ```text @@ -193,36 +193,36 @@ This document provides instructions to build and run Moddable SDK apps for the W cd ${MODDABLE}/build/makefiles/wasm make ``` - + 5. To test, build the `balls` example for the `wasm` target. ```text cd $MODDABLE/examples/piu/balls mcconfig -d -m -p wasm ``` - + You can run the app that's built in the browser by hosting it on a local HTTP server. Python provides a simple tool for doing this. - + If you are using Python 2: - + ```text cd $MODDABLE/build/bin/wasm/debug/balls python -m SimpleHTTPServer ``` - + If you are using Python 3: - + ```text cd $MODDABLE/build/bin/wasm/debug/balls python3 -m http.server ``` - + Go to [`localhost:8000`](http://localhost:8000) in a browser. You should see a web page with a simulator running `balls`. ## Limitations -Not all features of the Moddable SDK are supported in the Wasm simulator. +Not all features of the Moddable SDK are supported in the Wasm simulator. The following features are currently supported: @@ -236,4 +236,4 @@ The following features are not supported: - Socket - BLE - Pins/IO - + diff --git a/documentation/displays/readme.md b/documentation/displays/readme.md index ae47de5d12..2136b7359b 100644 --- a/documentation/displays/readme.md +++ b/documentation/displays/readme.md @@ -7,10 +7,10 @@ Revised: June 20, 2019 This folder contains guides to connect a variety of SPI displays to the ESP8266 and ESP32. Each guide contains: - General information about the display -- Links to the source code for the corresponding display and touch drivers +- Links to the source code for the corresponding display and touch drivers - A wiring guide - A build command to run an example app to test your wiring -Video demonstrations of these displays are [on the Moddable website](http://www.moddable.com/display). +Video demonstrations of these displays are [on the Moddable website](http://www.moddable.com/display). > Note: Although the guides in this folder are for the ESP8266 and ESP32, the examples and drivers are platform-independent and will run on any microcontroller the Moddable SDK is ported to. diff --git a/documentation/displays/wiring-guide-adafruit-1.8-st7735.md b/documentation/displays/wiring-guide-adafruit-1.8-st7735.md index 9b8d0faf20..440fbbb987 100644 --- a/documentation/displays/wiring-guide-adafruit-1.8-st7735.md +++ b/documentation/displays/wiring-guide-adafruit-1.8-st7735.md @@ -8,7 +8,7 @@ Revised: December 10, 2018 | | | | :---: | :--- | -| **Part** | Adafruit Product ID: 2088 +| **Part** | Adafruit Product ID: 2088 | **Size** | 1.8", 128 × 160 | **Type** | TFT LCD | **Interface** | SPI @@ -30,15 +30,15 @@ mcconfig -d -m -p esp/adafruit_st7735 | Adafruit 1.8" TFT | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| LITE | 3.3v | +| LITE | 3.3v | | MISO | GPIO 12 | (D6) | SCK | GPIO 14 | (D5) | MOSI | GPIO 13 | (D7) | TFT_CS | GPIO 15| (D8) | DC | GPIO 2 | (D4) -| RESET | 3.3v | -| VCC| 3.3v | -| GND | GND | +| RESET | 3.3v | +| VCC| 3.3v | +| GND | GND | ![Generic 2.4"-2.8" wiring illustration](images/adafruit-st7735-1.8-wiring.png) diff --git a/documentation/displays/wiring-guide-adafruit-OLED.md b/documentation/displays/wiring-guide-adafruit-OLED.md index 3fe30984ca..3b243ca995 100644 --- a/documentation/displays/wiring-guide-adafruit-OLED.md +++ b/documentation/displays/wiring-guide-adafruit-OLED.md @@ -8,14 +8,14 @@ Revised: October 23, 2018 | | | | :---: | :--- | -| **Part** | Adafruit Product ID: 1431 +| **Part** | Adafruit Product ID: 1431 | **Size** | 1.5", 128 × 128 | **Type** | OLED | **Interface** | SPI | **Drivers** | video [SSD1351](../../documentation/drivers/ssd1351/ssd1351.md), no touch | **Availability** | [1.5" OLED Breakout Board](https://www.adafruit.com/product/1431) | **Description** | Excellent color, small OLED. - + ## Moddable example code @@ -30,11 +30,11 @@ mcconfig -d -m -p esp/adafruit_oled | Adafruit OLED | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| GND | GND | -| VIN | 3.3v | -| 3Vo | 3.3v | +| GND | GND | +| VIN | 3.3v | +| 3Vo | 3.3v | | OLEDCS | GPIO 15| (D8) -| RESET | 3.3v | +| RESET | 3.3v | | DC | GPIO 2 | (D4) | SCK | GPIO 14 | (D5) | MOSI | GPIO 13 | (D7) diff --git a/documentation/displays/wiring-guide-crystalfontz-eink.md b/documentation/displays/wiring-guide-crystalfontz-eink.md index 6c2ca9c7e1..1c2463d312 100644 --- a/documentation/displays/wiring-guide-crystalfontz-eink.md +++ b/documentation/displays/wiring-guide-crystalfontz-eink.md @@ -9,7 +9,7 @@ Revised: October 23, 2018 | | | | :---: | :--- | | **Part** | CFAP128296C0-0290 ([datasheet](https://www.crystalfontz.com/products/document/3660/CFAP128296C0-0290DatasheetReleaseDate2017-08-14.pdf)) -| **Size** | 2.9" 128x296 +| **Size** | 2.9" 128x296 | **Type** | EPD (Electronic Paper Displays) | **Interface** | SPI | **Drivers** | video [destm32s](../../documentation/drivers/destm32s/destm32s.md), no touch @@ -29,16 +29,16 @@ mcconfig -d -m -p esp/crystalfontz_monochrome_epaper -r 270 | eInk Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| 3 - GND | GND | -| 5 - 3.3v | 3.3v | +| 3 - GND | GND | +| 5 - 3.3v | 3.3v | | 13 - SCK | GPIO 14 | (D5) | 14 - SDI | GPIO 13 | (D7) -| 15 - DC | GPIO 2 | (D4) -| 16 - CS | GPIO 4 | (D2) +| 15 - DC | GPIO 2 | (D4) +| 16 - CS | GPIO 4 | (D2) | 17 - BUSY | GPIO 5 | (D1) | 18 - Reset | 3.3v | -| 19 - BUSSEL | GND | - +| 19 - BUSSEL | GND | + ![Generic 2.4"-2.8" wiring illustration](images/eink+adaptor+esp-wiring.png) diff --git a/documentation/displays/wiring-guide-dotstar.md b/documentation/displays/wiring-guide-dotstar.md index 07aa66847e..b489269f72 100644 --- a/documentation/displays/wiring-guide-dotstar.md +++ b/documentation/displays/wiring-guide-dotstar.md @@ -8,7 +8,7 @@ Revised: December 11, 2018 | | | | :---: | :--- | -| **Size** | 144 LED strip (5mm x 5mm LEDs) +| **Size** | 144 LED strip (5mm x 5mm LEDs) | **Type** | ADA102 LED | **Interface** | SPI | **Drivers** | [dotstar](../../documentation/drivers/dotstar/dotstar.md) @@ -30,8 +30,8 @@ mcconfig -d -m -p esp | Dotstar Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| 5V | N/A (connect to 5V supply) | -| GND | GND | +| 5V | N/A (connect to 5V supply) | +| GND | GND | | CI | GPIO 14/SCLK | D5 | DI| GPIO 13/MOSI | D7 diff --git a/documentation/displays/wiring-guide-generic-1.44-spi.md b/documentation/displays/wiring-guide-generic-1.44-spi.md index f6165de761..b6d56931eb 100644 --- a/documentation/displays/wiring-guide-generic-1.44-spi.md +++ b/documentation/displays/wiring-guide-generic-1.44-spi.md @@ -27,15 +27,15 @@ mcconfig -d -m -p esp/generic_square ## ESP8266 Pinout | 1.44" Display | ESP8266 | ESP8266 Devboard label -| --- | --- | --- | +| --- | --- | --- | | VCC | 3.3V | -| GND | GND | +| GND | GND | | CS | GPIO 15 | (D8) -| RESET | 3.3V | +| RESET | 3.3V | | AO | GPIO 2 | (D4) -| SDA | GPIO 13 | (D7) -| SCK | GPIO 14 | (D5) -| LED | 3.3V | +| SDA | GPIO 13 | (D7) +| SCK | GPIO 14 | (D5) +| LED | 3.3V | ![Generic 2.4"-2.8" wiring illustration](images/esp-generic-1.44-display.jpg) diff --git a/documentation/displays/wiring-guide-generic-2.4-spi-esp32.md b/documentation/displays/wiring-guide-generic-2.4-spi-esp32.md index e848771d46..b2d156f396 100644 --- a/documentation/displays/wiring-guide-generic-2.4-spi-esp32.md +++ b/documentation/displays/wiring-guide-generic-2.4-spi-esp32.md @@ -27,22 +27,22 @@ mcconfig -d -m -p esp32/moddable_zero ## ESP32 Pinout -| ILI9341 Display | ESP32 | +| ILI9341 Display | ESP32 | | --- | --- | | SDO / MISO | GPIO 12 | -| LED | 3.3V | +| LED | 3.3V | | SCK | GPIO 14 | | SDI / MOSI | GPIO 13 | | CS | GPIO 15 | -| DC | GPIO 2 | -| RESET | 3.3V | -| GND | GND | -| VCC | 3.3V | -| T_DO | GPIO 12 | -| T_DIn | GPIO 13 | -| T_CLK | GPIO 14 | -| T_IRQ | GPIO 23 | -| T_CS | GPIO 18 | +| DC | GPIO 2 | +| RESET | 3.3V | +| GND | GND | +| VCC | 3.3V | +| T_DO | GPIO 12 | +| T_DIn | GPIO 13 | +| T_CLK | GPIO 14 | +| T_IRQ | GPIO 23 | +| T_CS | GPIO 18 | ![ESP32 - Generic 2.4"-2.8" wiring](images/ESP32+display-wiring2.png) diff --git a/documentation/displays/wiring-guide-generic-2.4-spi-pico.md b/documentation/displays/wiring-guide-generic-2.4-spi-pico.md index 3a40bc9843..62f33aa04a 100644 --- a/documentation/displays/wiring-guide-generic-2.4-spi-pico.md +++ b/documentation/displays/wiring-guide-generic-2.4-spi-pico.md @@ -28,7 +28,7 @@ mcconfig -d -m -p pico/ili9341 ## ili9341 Module pinout -This is a typical layout of the ili9341 module. +This is a typical layout of the ili9341 module. ![](./images/ili9341-pinout.png) @@ -51,4 +51,4 @@ This is a typical layout of the ili9341 module. | T_DIn | GPIO 11 | T_DO | GPIO 8 | T_IRQ | GPIO 14 ---> +--> diff --git a/documentation/displays/wiring-guide-generic-2.4-spi.md b/documentation/displays/wiring-guide-generic-2.4-spi.md index 90b6c37491..f0cf558b0f 100644 --- a/documentation/displays/wiring-guide-generic-2.4-spi.md +++ b/documentation/displays/wiring-guide-generic-2.4-spi.md @@ -30,20 +30,20 @@ mcconfig -d -m -p esp/moddable_zero | ILI9341 Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| SDO / MISO | GPIO 12 | (D6) -| LED | 3.3V | -| SCK | GPIO 14 | (D5) -| SDI / MOSI | GPIO 13 | (D7) +| SDO / MISO | GPIO 12 | (D6) +| LED | 3.3V | +| SCK | GPIO 14 | (D5) +| SDI / MOSI | GPIO 13 | (D7) | CS | GPIO 15 | (D8) -| DC | GPIO 2 | (D4) -| RESET | 3.3V | -| GND | GND | -| VCC | 3.3V | -| T_DO | GPIO 12 | (D6) -| T_DIn | GPIO 13 | (D7) -| T_CLK | GPIO 14 | (D5) +| DC | GPIO 2 | (D4) +| RESET | 3.3V | +| GND | GND | +| VCC | 3.3V | +| T_DO | GPIO 12 | (D6) +| T_DIn | GPIO 13 | (D7) +| T_CLK | GPIO 14 | (D5) | T_IRQ | GPIO 16 | (D0) -| T_CS | GPIO 0 | (D3) +| T_CS | GPIO 0 | (D3) ![Generic 2.4"-2.8" wiring illustration](images/esp-generic-2.4-display.png) diff --git a/documentation/displays/wiring-guide-generic-2.8-CPT-spi.md b/documentation/displays/wiring-guide-generic-2.8-CPT-spi.md index d842416500..86ac19458e 100644 --- a/documentation/displays/wiring-guide-generic-2.8-CPT-spi.md +++ b/documentation/displays/wiring-guide-generic-2.8-CPT-spi.md @@ -25,7 +25,7 @@ This display supports many configurations. For this sample, Moddable configured | --- | --- | | 4-wire SPI Interface | J2, J3, J4, J5 Short
J1, J6, J7, J8 Open
R1-R10=0R
R19=0R
R21-R28=0R
R17, R18, R20 not soldered -**Display input voltage** +**Display input voltage** The TFTM028-4 can be configured to be powered by either 5v or 3.3v via a solder jumper. See Table 4.3 in the [datasheet](http://www.buydisplay.com/download/manual/ER-TFTM028-4_Datasheet.pdf). For this guide the display was set to run with 3.3v input. If the display was configured for 5v Pin 2 on the display header would require 5v input. @@ -35,23 +35,23 @@ The [drag](../../examples/piu/drag/) example is good for testing this display. T ``` cd $MODDABLE/examples/piu/drag -mcconfig -d -m -p esp/buydisplay_ctp +mcconfig -d -m -p esp/buydisplay_ctp ``` ## ESP8266 Pinout | BuyDisplay CTP Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| 1 - VSS | GND | -| 2 - VDD | 3.3V | -| 21 - Reset | 3.3V | -| 23 - CS | GPIO 15 | (D8) +| 1 - VSS | GND | +| 2 - VDD | 3.3V | +| 21 - Reset | 3.3V | +| 23 - CS | GPIO 15 | (D8) | 24 - SCK | GPIO 14 | (D5) -| 25 - DC | GPIO 2 | (D4) +| 25 - DC | GPIO 2 | (D4) | 27 - SDI | GPIO 13 | (D7) | 28 - SDO | GPIO 12 | (D6) | 30 - CPT SCL | GPIO 4 | (D2) -| 31 - CPT SDA | GPIO 5 | (D1) +| 31 - CPT SDA | GPIO 5 | (D1) ![Generic 2.4"-2.8" wiring illustration](images/buydisplay+esp-wiring.png) diff --git a/documentation/displays/wiring-guide-sharp-memory-1.3-spi.md b/documentation/displays/wiring-guide-sharp-memory-1.3-spi.md index 07ccf5841c..e1e76df188 100644 --- a/documentation/displays/wiring-guide-sharp-memory-1.3-spi.md +++ b/documentation/displays/wiring-guide-sharp-memory-1.3-spi.md @@ -22,15 +22,15 @@ The [transitions](../../examples/piu/transitions/) example is good for testing t ``` cd $MODDABLE/examples/piu/transitions -mcconfig -d -m -p esp/sharp_memory_square +mcconfig -d -m -p esp/sharp_memory_square ``` ## ESP8266 Pinout | 1.3" Memory Display | ESP8266 | ESP8266 Devboard label -| --- | --- | --- | -| 3v3 | 3.3V | -| GND | GND | +| --- | --- | --- | +| 3v3 | 3.3V | +| GND | GND | | CLK | GPIO 14 | (D5) | DI | GPIO 13 | (D7) | CS | GPIO 15 | (D8) diff --git a/documentation/displays/wiring-guide-sharp-memory-2.7-spi.md b/documentation/displays/wiring-guide-sharp-memory-2.7-spi.md index c87e70f1cd..b13c922fd8 100644 --- a/documentation/displays/wiring-guide-sharp-memory-2.7-spi.md +++ b/documentation/displays/wiring-guide-sharp-memory-2.7-spi.md @@ -22,21 +22,21 @@ The [balls](../../examples/piu/balls/) example is good for testing this display. ``` cd $MODDABLE/examples/piu/balls -mcconfig -d -m -p esp/sharp_memory +mcconfig -d -m -p esp/sharp_memory ``` ## ESP8266 pinout | Sharp Memory Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| VIN | 3.3V | -| GND | GND | -| EXTMODE | | -| DISP | 3.3V | -| EXTCOMM | | -| SCS | GPIO 4 | (D2) -| SI | GPIO 13 | (D7) -| SCK | GPIO 14 | (D5) +| VIN | 3.3V | +| GND | GND | +| EXTMODE | | +| DISP | 3.3V | +| EXTCOMM | | +| SCS | GPIO 4 | (D2) +| SI | GPIO 13 | (D7) +| SCK | GPIO 14 | (D5) ![Generic SPI Display](images/wiring-Kuzyatech-sharp-2.7.jpg) diff --git a/documentation/displays/wiring-guide-sparkFun-teensyview-spi.md b/documentation/displays/wiring-guide-sparkFun-teensyview-spi.md index 03a398b532..550eeb12b2 100644 --- a/documentation/displays/wiring-guide-sparkFun-teensyview-spi.md +++ b/documentation/displays/wiring-guide-sparkFun-teensyview-spi.md @@ -8,7 +8,7 @@ Revised: October 23, 2018 | | | | :---: | :--- | -| **Part** | Sparkfun - LCD-14048 +| **Part** | Sparkfun - LCD-14048 | **Size** | 128 x 32 | **Type** | OLED, Monochrome |**Interface** | SPI @@ -16,25 +16,25 @@ Revised: October 23, 2018 |**Availability** | [TeensyView on Sparkfun](https://www.sparkfun.com/products/14048) |**Description** | Very small monochrome, OLED display. Moddable uses the TeensyView configured in [standard](https://learn.sparkfun.com/tutorials/teensyview-hookup-guide) mode. -## Moddable example code +## Moddable example code The [balls](../../examples/piu/balls/) example is good for testing this display. To run a debug build, use the following build command: ``` cd $MODDABLE/examples/piu/balls -mcconfig -d -m -p esp/teensyview +mcconfig -d -m -p esp/teensyview ``` ## ESP8266 pinout | TeensyView Display | ESP8266 | ESP8266 Devboard label | --- | --- | --- | -| GND | GND | +| GND | GND | | 5 | GPIO 2 | (D4) | 10 | GPIO 4 | (D2) -| 11 | GPIO 13 | (D7) -| 13 | GPIO 14 | (D5) -| 15 | GPIO 0 | (D3) +| 11 | GPIO 13 | (D7) +| 13 | GPIO 14 | (D5) +| 15 | GPIO 0 | (D3) | 3v | 3.3V | ![Generic SPI Display](images/teensyview-wiring.jpg) diff --git a/documentation/displays/wiring-guide-switch-science-LCD.md b/documentation/displays/wiring-guide-switch-science-LCD.md index 8af0fd771e..929b9008c3 100644 --- a/documentation/displays/wiring-guide-switch-science-LCD.md +++ b/documentation/displays/wiring-guide-switch-science-LCD.md @@ -8,7 +8,7 @@ Revised: October 23, 2018 | | | | :---: | :--- | -| **Part** | 2858: JDI - REFLCD - 128 +| **Part** | 2858: JDI - REFLCD - 128 | **Size** | 1.28", 176 × 176 | **Type** | Color reflective LCD (no backlight) | **Interface** | SPI @@ -30,11 +30,11 @@ mcconfig -d -m -p esp/switch_science_reflective_lcd | Switch Science LCD | ESP8266 | ESP8266 Devboard label | --- | --- | --- | | 14 - SCLK | GPIO 14 | (D5) -| 13 - SI | GPIO 13 | (D7) +| 13 - SI | GPIO 13 | (D7) | 15 - SCS | GPIO 15 | (D8) -| DISP | 3.3v | -| GND | GND | -| VIN | 3.3v | +| DISP | 3.3v | +| GND | GND | +| VIN | 3.3v | ![Generic 2.4"-2.8" wiring illustration](images/switch-science-esp-wiring.png) diff --git a/documentation/drivers/MCP230XX/MCP230XX.md b/documentation/drivers/MCP230XX/MCP230XX.md index e618e17ee7..ca72e1a489 100644 --- a/documentation/drivers/MCP230XX/MCP230XX.md +++ b/documentation/drivers/MCP230XX/MCP230XX.md @@ -11,15 +11,15 @@ The [MCP23017](http://www.microchip.com/wwwproducts/en/MCP23017) device provides The driver module "MCP230XX" exports the following: ```js -export { - MCP23008, +export { + MCP23008, MCP23017 }; ``` ### MCP23008 Class -The `MCP23008` class produces instances that represent a single MCP23008 IC on the I2C bus. The `MCP23008` class extends an internal `Expander` class, which extends the `SMBus` class. `Expander` is not exported. +The `MCP23008` class produces instances that represent a single MCP23008 IC on the I2C bus. The `MCP23008` class extends an internal `Expander` class, which extends the `SMBus` class. `Expander` is not exported. Instance objects of `MCP23008` contain 8 `Pin` instance object entries. @@ -63,8 +63,8 @@ let leds = new MCP23008({ sda: 4, scl: 5 }); | Parameter | Type | Default Value | Description | --- | --- | --- | :--- | | `address` | `number` | `0x20` | The address of the I2C device | -| `hz` | `number` | 100kHz | The clock speed of the I2C device. | -| `sda` | `number` | 4 | The I2C sda (data) pin. | +| `hz` | `number` | 100kHz | The clock speed of the I2C device. | +| `sda` | `number` | 4 | The I2C sda (data) pin. | | `scl` | `number` | 5 | The I2C scl (clock) pin. | | `inputs` | `number` (byte) | `0b11111111` | A byte representing the input/output initialization state of the 8 GPIO pins. `1` for input, `0` for output | | `pullups` | `number` (byte) | `0b00000000` | A byte representing the pullup initialization state of the 8 GPIO pins. `1` for pullup, `0` for default | @@ -86,7 +86,7 @@ All properties are read-only. ##### `write(byte)` -Temporarily sets the mode of all pins to output and writes all pins at once. +Temporarily sets the mode of all pins to output and writes all pins at once. ```js let expander = new MCP23008(); // defaults to 0x20! @@ -99,7 +99,7 @@ Temporarily sets the mode of all pins to input, reads all pins at once, and retu ```js let expander = new MCP23008(); // defaults to 0x20! -trace(`${expander.read()}\n`); +trace(`${expander.read()}\n`); ``` @@ -157,7 +157,7 @@ let leds = new MCP23017({ sda: 4, scl: 5 }); #### Properties -All properties are read-only. +All properties are read-only. | Name | Type | Value | Description| | --- | --- | --- | :--- | @@ -173,7 +173,7 @@ All properties are read-only. ##### `write(word)` -Temporarily sets the mode of all pins to output and writes all pins at once. +Temporarily sets the mode of all pins to output and writes all pins at once. ```js let expander = new MCP23017(); // defaults to 0x20! @@ -186,7 +186,7 @@ Temporarily sets the mode of all pins to input, reads all pins at once, and retu ```js let expander = new MCP23017(); // defaults to 0x20! -trace(`${expander.read()}\n`); +trace(`${expander.read()}\n`); ``` ### Pin Class @@ -201,7 +201,7 @@ export default function() { const leds = new MCP23008({ inputs: 0b00000000 }); - + // leds[0], leds[1], etc. are Pin instances leds[0].write(1); leds[1].write(0); @@ -237,7 +237,7 @@ export default function() { All properties are read-only. -| Name | Type | Description +| Name | Type | Description | --- | --- | :--- | | `pin` | `number` | The GPIO pin number | | `expander` | `expander` | The instance of `Expander` that this `Pin` belongs to | @@ -250,7 +250,7 @@ All properties are read-only. | --- | --- | :--- | | `mode` | `number` | A number representing the desired mode. May be input, input pullup, or output. -Sets the pin's mode to the specified mode. +Sets the pin's mode to the specified mode. ##### `read()` diff --git a/documentation/drivers/destm32s/destm32s.md b/documentation/drivers/destm32s/destm32s.md index 5263123eeb..1e886bea02 100644 --- a/documentation/drivers/destm32s/destm32s.md +++ b/documentation/drivers/destm32s/destm32s.md @@ -66,11 +66,11 @@ For 104 x 212 black, white, gray, and red: } ### Configuring SPI -The `defines` object must contain the `spi_port`, along with the `DC`, `CS`, and `BUSY`. pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, `rst_port`, or `busy_port` properties are not provided, they default to NULL. +The `defines` object must contain the `spi_port`, along with the `DC`, `CS`, and `BUSY`. pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, `rst_port`, or `busy_port` properties are not provided, they default to NULL. "defines": { "ssd1351": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "dc_pin": 2, "rst_pin": 0, diff --git a/documentation/drivers/dotstar/dotstar.md b/documentation/drivers/dotstar/dotstar.md index ef34c28d55..609643319d 100644 --- a/documentation/drivers/dotstar/dotstar.md +++ b/documentation/drivers/dotstar/dotstar.md @@ -31,11 +31,11 @@ In the `defines` object, the optional `brightness` property may be set, where 25 } ### Configuring SPI -The `defines` object must contain the `spi_port`. +The `defines` object must contain the `spi_port`. "defines": { "dotstar": { - /* other properties here */ + /* other properties here */ "spi_port": "#HSPI" } } diff --git a/documentation/drivers/ili9341/ili9341.md b/documentation/drivers/ili9341/ili9341.md index 00e5bb9829..26cdfce84f 100644 --- a/documentation/drivers/ili9341/ili9341.md +++ b/documentation/drivers/ili9341/ili9341.md @@ -48,7 +48,7 @@ In the `defines` object, declare the pixel `width` and `height`. } } -The optional `registers` property is used to override the default initialization of registers on the ILI9341. The register property is compiled in C as part of the driver source code, so it has access to the same #define constants as the driver, hence the use of `kDelayMS`, `MODDEF_ILI9341_FLIPY`, and `MODDEF_ILI9341_FLIPX` below. The list of register commands is terminated with pseudo-registers `kDelayMS` with a value of 0. +The optional `registers` property is used to override the default initialization of registers on the ILI9341. The register property is compiled in C as part of the driver source code, so it has access to the same #define constants as the driver, hence the use of `kDelayMS`, `MODDEF_ILI9341_FLIPY`, and `MODDEF_ILI9341_FLIPX` below. The list of register commands is terminated with pseudo-registers `kDelayMS` with a value of 0. "defines": { "ili9341": { @@ -80,11 +80,11 @@ The optional `registers` property is used to override the default initialization } ### Configuring SPI -The `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. +The `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. "defines": { "ili9341": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "dc_pin": 2, "rst_pin": 0, diff --git a/documentation/drivers/lpm013m126a/lpm013m126a.md b/documentation/drivers/lpm013m126a/lpm013m126a.md index 26b8490c34..ff72e6340a 100644 --- a/documentation/drivers/lpm013m126a/lpm013m126a.md +++ b/documentation/drivers/lpm013m126a/lpm013m126a.md @@ -43,11 +43,11 @@ The driver's dithering implementation operates on eight rows of pixels at a time touchCount: 0, pixels: 176 * 8 }); ### Configuring SPI -The `defines` object must contain the `spi_port`, along with the `CS` pin number. If the `cs_port` property is not provided, it defaults to NULL. +The `defines` object must contain the `spi_port`, along with the `CS` pin number. If the `cs_port` property is not provided, it defaults to NULL. "defines": { "lpm013m126a": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "spi_port": "#HSPI", } diff --git a/documentation/drivers/ls013b4dn04/ls013b4dn04.md b/documentation/drivers/ls013b4dn04/ls013b4dn04.md index fe0af8a854..b41b3ccc68 100644 --- a/documentation/drivers/ls013b4dn04/ls013b4dn04.md +++ b/documentation/drivers/ls013b4dn04/ls013b4dn04.md @@ -35,11 +35,11 @@ In the `defines` object, declare the pixel `width` and `height`. } ### Configuring SPI -The `defines` object must contain the `spi_port`, along with the `CS` pin number. If the `cs_port` property is not provided, it defaults to NULL. +The `defines` object must contain the `spi_port`, along with the `CS` pin number. If the `cs_port` property is not provided, it defaults to NULL. "defines": { "ls013b4dn04": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "spi_port": "#HSPI", } diff --git a/documentation/drivers/neostrand/neostrand.md b/documentation/drivers/neostrand/neostrand.md index f3bc8ed4dc..b0cc956559 100644 --- a/documentation/drivers/neostrand/neostrand.md +++ b/documentation/drivers/neostrand/neostrand.md @@ -49,7 +49,7 @@ const strand = new NeoStrand({length: 50, pin: 22, order: "RGB",   > Note: You may want to tone down your lights during development so you don't blind yourself. -> +> > ```js > strand.brightness(10); > ``` @@ -125,7 +125,7 @@ start | `0` | [0..strand.length] | The index of the first pixel of effect end | `strand.length` | [0..strand.length] | The index of the last pixel of effect size | `strand.length` | [0..strand.length] | The length of one hue cycle, in pixels duration | `1000` | | The duration of one complete cycle of the effect, in ms -reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards +reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards loop | `1` | [0, 1] | Set to 1 to loop the effect `start` and `end` define the span of pixels that this effect will operate on. `duration` is the length of one cycle of the effect. @@ -197,7 +197,7 @@ start | `0` | [0..strand.length] | The index of the first pixel of effect end | `strand.length` | [0..strand.length] | The index of the last pixel of effect size | `strand.length` | [0..strand.length] | The length of one hue cycle, in pixels duration | 1000 | | time of one complete cycle of the pattern, in ms -reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards +reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards loop | `1` | [0, 1] | Set to 1 to loop the effect sizeA | 1 | [1..strand.length] | number of pixels in the A part of pattern sizeB | 3 | [1..strand.length] | number of pixels in the B part of pattern @@ -218,7 +218,7 @@ start | `0` | [0..strand.length] | The index of the first pixel of effect end | `strand.length` | [0..strand.length] | The index of the last pixel of effect size | `strand.length` | [0..strand.length] | The length of one hue cycle, in pixels duration | 1000 | | time of one complete cycle of the color wheel, in ms -reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards +reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards loop | `1` | [0, 1] | Set to 1 to loop the effect speed | 1.0 | | speed multiplier position | 0 | [0..1] | starting HSV hue position @@ -240,7 +240,7 @@ start | `0` | [0..strand.length] | The index of the first pixel of effect end | `strand.length` | [0..strand.length] | The index of the last pixel of effect size | `strand.length` | [0..strand.length] | The length of one hue cycle, in pixels duration | 1000 | | time of one complete sine cycle, in ms -reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards +reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards loop | `1` | [0, 1] | Set to 1 to loop the effect speed | 1.0 | | speed multiplier loop | 1 | [0, 1] | loop the effect @@ -262,7 +262,7 @@ start | `0` | [0..strand.length] | The index of the first pixel of effect end | `strand.length` | [0..strand.length] | The index of the last pixel of effect size | `strand.length` | [0..strand.length] | The length of one hue cycle, in pixels duration | 3000 | | time of one pulse cycle, in ms -reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards +reverse | `0` | [0, 1] | Set to 1 to run the effect in reverse, i.e. run the timeline of the effect backwards loop | `1` | [0, 1] | Set to 1 to loop the effect position | "random" | [-strand.length..strand.length] | index of the pulse starting pixel
negative numbers are off-strand and okay
"random" picks a random starting location mode | 1 | [-1, 0, 1] | **1** to add, **-1** to subtract, or **0** set the pixel color @@ -314,7 +314,7 @@ size | 5 | [0..strand.length] | size of each color max | 127 | [0..255] | maximium value of random RGB component Using *Pattern* as a starting point, we'll change the class name and constructor, set up the timeline in `activate` and provide a setter for the changing `effectValue`. The `loopPrepare` function will be called before a looping effect starts or restarts. - + ```js class RandomColor extends NeoStrandEffect { @@ -356,7 +356,7 @@ manySchemes.push( randomColorScheme ); ## Timing -Timing specifications for the various driver chips of the LEDs are included for reference below. +Timing specifications for the various driver chips of the LEDs are included for reference below. ```js const Timing_WS2812B = { diff --git a/documentation/drivers/ssd1306/ssd1306.md b/documentation/drivers/ssd1306/ssd1306.md index a30e9463cc..6d9b0b7961 100644 --- a/documentation/drivers/ssd1306/ssd1306.md +++ b/documentation/drivers/ssd1306/ssd1306.md @@ -47,11 +47,11 @@ The SSD1306 driver implements optional dithering. Dithering allows an approximat } ### Using SPI -When using a SPI interface, the `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. +When using a SPI interface, the `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. "defines": { "ssd1306": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "dc_pin": 2, "rst_pin": 0, @@ -68,7 +68,7 @@ When using an I2C interface, the `defines` object may contain the I2C address of "defines": { "ssd1306": { - /* other properties here */ + /* other properties here */ "scl_pin": 4, "sda_pin": 5, "address": 0x3c, diff --git a/documentation/drivers/ssd1351/ssd1351.md b/documentation/drivers/ssd1351/ssd1351.md index 837588a870..b9075b1562 100644 --- a/documentation/drivers/ssd1351/ssd1351.md +++ b/documentation/drivers/ssd1351/ssd1351.md @@ -33,7 +33,7 @@ In the `defines` object, declare the pixel `width` and `height`. "height": 128, } } - + The optional `offset_column` and `offset_row` properties offset the `x` and `y` position of the image within the display, which is useful for some configurations. "defines": { @@ -76,11 +76,11 @@ The optional `initialization` property is used to override the default initializ } ### Configuring SPI -The `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. +The `defines` object must contain the `spi_port`, along with the `DC` and `CS` pin numbers. If a `RST` pin is provided, the device will be reset when the constructor is invoked. If the `cs_port`, `dc_port`, or `rst_port` properties are not provided, they default to NULL. "defines": { "ssd1351": { - /* other properties here */ + /* other properties here */ "cs_pin": 4, "dc_pin": 2, "rst_pin": 0, diff --git a/documentation/files/files.md b/documentation/files/files.md index 21c86e7d31..78d1c38b09 100644 --- a/documentation/files/files.md +++ b/documentation/files/files.md @@ -37,7 +37,7 @@ As a rule, scripts should always prefix full paths with this root. The forward slash character (`/`) is always used as a path separator, even on hosts that natively use a different path separator. -The `System.config()` function, described below, provides the length of the longest supported path through the `maxPathLength` property. +The `System.config()` function, described below, provides the length of the longest supported path through the `maxPathLength` property. ### class File @@ -232,7 +232,7 @@ Directory.delete(config.file.root + "tmp"); - **Source code:** [file](../../modules/files/file) - **Relevant Examples:** [files](../../examples/files/files/) -The File `Iterator` class enumerates the files and subdirectories in a directory. +The File `Iterator` class enumerates the files and subdirectories in a directory. ```js import {Iterator} from "file"; @@ -420,7 +420,7 @@ By default, the FAT32 file system is mounted at `/mod`. To change the default ro #### littlefs The [littlefs](https://github.com/littlefs-project/littlefs) file system is "a little fail-safe filesystem designed for microcontrollers." It provides a high reliability, hierarchical file system in a small code footprint (about 60 KB) using minimal memory (well under 1 KB) with a high degree of configurability. littlefs also supports long file names (up to 255 characters) and formats a new partition very quickly. -The Moddable SDK supports littlefs using the APIs described above. To use littlefs, include its manifest. +The Moddable SDK supports littlefs using the APIs described above. To use littlefs, include its manifest. ```json "includes": { @@ -433,7 +433,7 @@ The Moddable SDK supports littlefs using the APIs described above. To use little The backing store for littlefs varies depending the host platform: - **ESP32** - littlefs uses the "storage" partition to hold the file system. -- **ESP8266** - the file system is stored in the upper 3 MB of flash (the same area used by SPIFFS). +- **ESP8266** - the file system is stored in the upper 3 MB of flash (the same area used by SPIFFS). - **nRF52** - littlefs uses the free space following the firmware image and installed mod. The default size is 64 KB, which may be overridden by `MODDEF_FILE_LFS_PARITION_SIZE` in the manifest `defines`. If there is not enough space, an exception is thrown when accessing the file system. - **Others**, littlefs uses a static memory buffer to hold the file system. The default size is 64 KB, which may be overridden by `MODDEF_FILE_LFS_PARITION_SIZE` in the manifest. This RAM disk mode allows littlefs to be used with the simulator. @@ -637,7 +637,7 @@ The `Preference` class provides storage of persistent preference storage. Prefer ```js import Preference from "preference"; ``` - + Preferences are grouped by domain. A domain contains one or more keys. Each domain/key pair holds a single value, which is either a `Boolean`, integer (e.g. `Number` with no fractional part), `String` or `ArrayBuffer`. ```js @@ -692,13 +692,13 @@ Preference.delete("wifi", "password"); ### `static keys(domain)` Returns an array of all keys under the given domain. - + ```js let wifiKeys = Preference.keys("wifi"); for (let key of wifiKeys) trace(`${key}: ${Preference.get("wifi", key)}\n`); ``` - + *** diff --git a/documentation/io/firmata.md b/documentation/io/firmata.md index 23272e0ca7..14d0cc6eb8 100644 --- a/documentation/io/firmata.md +++ b/documentation/io/firmata.md @@ -7,13 +7,13 @@ The Moddable SDK contains an implementation of the Firmata protocol for communic The primary goal of the implementation is to explore using the new IO class. The Firmata protocol is an interesting test case as it exercises many different kinds of IO. The Firmata protocol has been invaluable in this regard. The resulting Firmata implementation may also be useful more broadly. As the TC53 IO class becomes available on other hardware platforms, this Firmata implementation should run more-or-less as-is there, perhaps providing Firmata support on additional hardware hosts. -> **Note**: The IO Class implementation is available only for the ESP8266 microcontroller which was selected as the initial target because it is representative of resource constrained devices, widely available, well-understood at Moddable, and inexpensive. +> **Note**: The IO Class implementation is available only for the ESP8266 microcontroller which was selected as the initial target because it is representative of resource constrained devices, widely available, well-understood at Moddable, and inexpensive. The Firmata protocol is effectively a client/server protocol with the microcontroller taking the role of the server, and the device controller, often a computer, taking the role of the client. In the Firmata ecosystem, [Firmata.js](https://github.com/firmata/firmata.js#firmatajs) is a popular client, providing a [JavaScript API](https://github.com/firmata/firmata.js/tree/master/packages/firmata.js#firmata-prototype-api) in the Node.js environment to communicate with Firmata servers. There are [many other](https://github.com/firmata/arduino#firmata-client-libraries) Firmata clients available for various languages and environments. There are many fewer implementations of the Firmata server, with the [Standard Firmata Adruino implementation](https://github.com/firmata/arduino#firmata) being the most commonly used. -The implementation of Firmata in the Moddable SDK includes both a client and server. Each is implemented in JavaScript using the proposed TC53 IO class APIs. In the case of the client, it presents Firmata as a TC53 IO class provider. +The implementation of Firmata in the Moddable SDK includes both a client and server. Each is implemented in JavaScript using the proposed TC53 IO class APIs. In the case of the client, it presents Firmata as a TC53 IO class provider. -Implementing both the client and server allowed more uses of the IO class to be explored. The server implementation was developed against the Firmata.js client; the client implementation, against the server. The Firmata.js and Arduino Firmata server code were consulted to supplement the information in the protocol documentation. +Implementing both the client and server allowed more uses of the IO class to be explored. The server implementation was developed against the Firmata.js client; the client implementation, against the server. The Firmata.js and Arduino Firmata server code were consulted to supplement the information in the protocol documentation. > **Note:** To build and run the examples in this document, you must have already installed the Moddable SDK and followed the instructions to set up the build tools for the ESP8266 target from the [Getting Started document](../Moddable%20SDK%20-%20Getting%20Started.md). @@ -55,11 +55,11 @@ To build and run the Firmata server, execute the following commands: cd $MODDABLE/examples/io/firmata/server mcconfig -m -p esp -This builds and deploys the Firmata server to an ESP8266. Note that this a release build, not a debug build. This is because Firmata uses the serial port for communication, which precludes it from being by the xsbug debugger to communicate with the ESP8266. +This builds and deploys the Firmata server to an ESP8266. Note that this a release build, not a debug build. This is because Firmata uses the serial port for communication, which precludes it from being by the xsbug debugger to communicate with the ESP8266. From here, the Firmata.js server may be used as usual with Firmata clients. Note that the Firmata server does not announce itself over serial so it is necessary to wait about five seconds for Firmata.js to issue a probe request before the connection is fully established. -The Firmata server implementation supports the following standard pin types: +The Firmata server implementation supports the following standard pin types: - digital input - digital input pull-up @@ -67,9 +67,9 @@ The Firmata server implementation supports the following standard pin types: - analog input - serial -The pins that are available depend on the configuration. For example, only a single serial port is available in the implementation. If that port is being used for Firmata transport, it is unavailable for use by a Firmata client. +The pins that are available depend on the configuration. For example, only a single serial port is available in the implementation. If that port is being used for Firmata transport, it is unavailable for use by a Firmata client. -The Firmata Server was tested primarily on a [Moddable One](https://www.moddable.com/moddable-one.php), which combines an ESP8266 with a high quality IPS display and capacitive touch screen. +The Firmata Server was tested primarily on a [Moddable One](https://www.moddable.com/moddable-one.php), which combines an ESP8266 with a high quality IPS display and capacitive touch screen. ### Example code @@ -144,7 +144,7 @@ void board.i2cStop(0x38) ### Communicating with the Firmata Server Over TCP -The Firmata server implements communication over a TCP network connection, in addition to serial. The Firmata server can operate in TCP in two different ways. One way is by initiating a TCP connection to a Firmata client, in which case (confusingly) the Firmata server is acting as a TCP client while the Firmata client is acting as a TCP server. This is the more common way. Alternatively, it can listen for an incoming TCP request from a Firmata client, in which case the Firmata server is a TCP server and the Firmata client is a TCP client. +The Firmata server implements communication over a TCP network connection, in addition to serial. The Firmata server can operate in TCP in two different ways. One way is by initiating a TCP connection to a Firmata client, in which case (confusingly) the Firmata server is acting as a TCP client while the Firmata client is acting as a TCP server. This is the more common way. Alternatively, it can listen for an incoming TCP request from a Firmata client, in which case the Firmata server is a TCP server and the Firmata client is a TCP client. #### Using `FirmataTCPClient` To configure the Firmata server to initiate a TCP connection to a Firmata client, do the following: @@ -215,7 +215,7 @@ The I2C bus on Moddable One uses pin 5 for data and pin 4 for a clock. The primary serial connection on ESP8266 uses pin 1 for TX and pin 3 for RX. -The Moddable Firmata Server implementation combines a general purpose Firmata server with specific knowledge of the ESP2866 pin configuration. The ESP8266 knowledge is largely isolated and should eventually migrate to a separate file to ease supporting additional microcontrollers. +The Moddable Firmata Server implementation combines a general purpose Firmata server with specific knowledge of the ESP2866 pin configuration. The ESP8266 knowledge is largely isolated and should eventually migrate to a separate file to ease supporting additional microcontrollers. The Firmata Server implements the optional `STRING_DATA` message with the `doSendString` function which allows the server implementation to send short text strings to the client. These messages have no meaning defined in the protocol. They proved useful for debugging to generate a simple console trace from the server to the client, which is not possible when communicating with Firmata over serial which makes the xsbug debugging connection unavailable. To output these messages to the console using Firmata.js, add this line: @@ -236,7 +236,7 @@ To build and run the Firmata client, execute the following commands: cd $MODDABLE/examples/io/firmata/client mcconfig -d -m -p esp ssid="Moddable" password="secret" -This builds and deploys the Firmata client to an ESP8266. Note that unlike the server, this a debug build, as the examples will only use Firmata over TCP, not serial. +This builds and deploys the Firmata client to an ESP8266. Note that unlike the server, this a debug build, as the examples will only use Firmata over TCP, not serial. The Client API is the proposed TC53 IO provider class. An IO provider is an object that gives access to one or more kinds of IO. The IO it provides access to may be remote, as is the case with the Firmata use described here, or local, for example an GPIO expander connected over I2C. @@ -286,7 +286,7 @@ let led = new firmata.Digital({ pin: 2, mode: firmata.Digital.Output, }); - + let value = 0; System.setInterval(() => { led.write(value); @@ -295,7 +295,7 @@ System.setInterval(() => { ``` #### Monitor Remote Flash Button - + ```js let remoteButton = new firmata.Digital({ pin: 0, @@ -339,7 +339,7 @@ let remoteBank = new firmata.DigitalBank({ ``` #### I2C -I2C is a bit more complicated than Analog and Digital pins as it is a transaction-based hardware protocol: requests are made to the hardware to read and write bytes. The provider is fully asynchronous. This is not a problem for write operations as the Firmata protocol assumes reliable delivery, so the write request will eventually be delivered to the write pins. +I2C is a bit more complicated than Analog and Digital pins as it is a transaction-based hardware protocol: requests are made to the hardware to read and write bytes. The provider is fully asynchronous. This is not a problem for write operations as the Firmata protocol assumes reliable delivery, so the write request will eventually be delivered to the write pins. ```js let i2c = new firmata.I2C({ @@ -452,7 +452,7 @@ Colors are transmitted from client to server using seven bits per channel (R, G, The Firmata Server informs the client that the Poco protocol extension is supported by sending a `STRING_DATA` message with the value `hasPoco` following the response to the `CAPABILITY_QUERY` message. A client which is unaware of the feature will ignore the message. This is a temporary ad-hoc approach. -All Poco messages contained within the Sysex message `User Command 1` to avoid conflicting with any existing or proposed extension to Firmata. +All Poco messages contained within the Sysex message `User Command 1` to avoid conflicting with any existing or proposed extension to Firmata. ## Conclusion diff --git a/documentation/io/io.md b/documentation/io/io.md index a371ddbcb5..d1a9421fad 100644 --- a/documentation/io/io.md +++ b/documentation/io/io.md @@ -1,4 +1,4 @@ -# TC53 IO: A New Take on JavaScript Input/Output on Microcontrollers +# TC53 IO: A New Take on JavaScript Input/Output on Microcontrollers Author: Peter Hoddie
Updated: April 7, 2021
Copyright 2019-2021 Moddable Tech, Inc. @@ -20,7 +20,7 @@ The remainder of this document describes the IO Class Pattern and how it is appl ## The Basic IO Pattern The IO Class Pattern design starts with the idea that the majority of IO operations on a microcontroller are described by four basic operations: -1. **Create** -- Establish and configure a connection to an IO resource. +1. **Create** -- Establish and configure a connection to an IO resource. 1. **Read** -- Get data from the IO resource. 1. **Write** -- Send data to the IO resource. 1. **Close** -- Release the IO resource. @@ -58,7 +58,7 @@ let serial = new Serial({ }) ``` -This way of providing the callback as a property of the configuration is often convenient. The same approach is used by streams in Node.js as described in [Simplified Construction](https://nodejs.org/api/stream.html#stream_simplified_construction). +This way of providing the callback as a property of the configuration is often convenient. The same approach is used by streams in Node.js as described in [Simplified Construction](https://nodejs.org/api/stream.html#stream_simplified_construction). Each IO implementation defines the notifications it supports. The IO Class Pattern proposal defines four notifications: @@ -96,10 +96,10 @@ Scripts that perform read operations may call read at any time. To avoid polling Most kinds of IO have one of the following behaviors for their read operation: -- Return the current value of the IO resource. +- Return the current value of the IO resource. Examples of this include digital inputs and analog inputs. Performing a read operation does not change what will be returned by the next read operation. Only changes to the IO resource itself change the value. The `onReadable` callback is invoked when the value of the IO resource changes. -- Return data from the input buffer. +- Return data from the input buffer. Examples of this include serial and TCP network connections. Once data is read from a serial connection, that data is removed from the input buffer. A subsequent read will receive the next data in the buffer. The `onReadable` callback is invoked when new data is received. @@ -132,10 +132,10 @@ new Serial({ Most kinds of IO have one of the following behaviors for their write operation: -- Change the current value output by the IO resource. +- Change the current value output by the IO resource. A digital output is an example of this behavior. Performing a write operation immediately changes what is output by the IO resource. The `onWritable` callback is not useful for this case, as the value may be changed at any time. -- Add data to the output buffer. +- Add data to the output buffer. Examples of this include serial and TCP network connections. Once data is written from a serial connection, that data is transmitted over a period of time. The `onWritable` callback is invoked when space has been freed in the output buffer. @@ -375,7 +375,7 @@ let pwm = new PWM({ pin: 5, hz: 10000 }); pwm.write(0.5 * ((1 << pwm.resolution) - 1)); ``` -### I2C +### I2C The built-in `I2C` class implements an I2C Master to communicate with one address on an I2C bus. ```js @@ -399,7 +399,7 @@ The data format is always a buffer. The `write` call accepts an `ArrayBuffer` or #### Use Notes Many I2C buses use the higher-level SMB protocol, an extension to the I2C protocol that simplifies its use. The `SMBus` class is a subclass of the `I2C` class that provides support for working with SMBus devices. -The I2C protocol is transaction-based. At the end of each read and write operation, a stop bit is sent. If the stop bit is 1, it indicates the end of the transaction; if 0, it indicates that there are additional operations on the transaction. The `read` and `write` calls set the stop bit to 1 by default. An optional second parameter to the `read` and `write` allows the stop bit to be specified. Pass `false` to set the stop bit to 0, and `true` to set the stop bit to 1. +The I2C protocol is transaction-based. At the end of each read and write operation, a stop bit is sent. If the stop bit is 1, it indicates the end of the transaction; if 0, it indicates that there are additional operations on the transaction. The `read` and `write` calls set the stop bit to 1 by default. An optional second parameter to the `read` and `write` allows the stop bit to be specified. Pass `false` to set the stop bit to 0, and `true` to set the stop bit to 1. #### Example The following example reads the number of touch points from an FT6206 touch sensor, and then retrieves the X and Y coordinates for the active touch points. @@ -437,7 +437,7 @@ import Serial from "embedded:io/serial"; | :---: | :--- | | `baud` | A number specifying the baud rate of the connection. This property is required. -> **Note**: No pins are specified because there is only a single full-duplex hardware serial port on the ESP8266, which is always connected to GPIO pins 1 and 3. +> **Note**: No pins are specified because there is only a single full-duplex hardware serial port on the ESP8266, which is always connected to GPIO pins 1 and 3. #### Callbacks @@ -487,7 +487,7 @@ The following example continuously outputs text to the serial output. It uses th const message = ArrayBuffer.fromString("Since publication of the first edition in 1997, ECMAScript has grown to be one of the world's most widely used general-purpose programming languages. It is best known as the language embedded in web browsers but has also been widely adopted for server and embedded applications.\r\n"); let offset = 0; - + const serial = new Serial({ baud: 921600, onWritable: function(count) { @@ -505,7 +505,7 @@ serial.format = "buffer"; ``` ### TCP Socket -The built-in `TCP` network socket class implements a general purpose, bi-directional TCP connection. +The built-in `TCP` network socket class implements a general purpose, bi-directional TCP connection. ```js import TCP from "embedded:io/socket/tcp"; @@ -623,14 +623,14 @@ class TCPEcho { } onReadable() { const response = this.read(); - + this.write(ArrayBuffer.fromString("HTTP/1.1 200 OK\r\n")); this.write(ArrayBuffer.fromString("connection: close\r\n")); this.write(ArrayBuffer.fromString("content-type: text/plain\r\n")); this.write(ArrayBuffer.fromString(`content-length: ${response.byteLength}\r\n`)); this.write(ArrayBuffer.fromString("\r\n")); this.write(response); - + this.close(); } } @@ -648,7 +648,7 @@ new Listener({ ``` ### UDP Socket -The built-in `UDP` network socket class implements the sending and receiving of UDP packets. +The built-in `UDP` network socket class implements the sending and receiving of UDP packets. ```js import UDP from "embedded:io/socket/udp"; @@ -669,7 +669,7 @@ Invoked when one or more packets are received. The callback receives a single ar The data format is always `buffer`. The `write` call accepts an `ArrayBuffer` or a `TypedArray`. The `read` call always returns an `ArrayBuffer`. #### Use Notes -The `read` call returns a complete UDP packet as an `ArrayBuffer`. Partial reads are not supported. The returned packet data has two properties attached to it: +The `read` call returns a complete UDP packet as an `ArrayBuffer`. Partial reads are not supported. The returned packet data has two properties attached to it: - `address`, a string containing the packet sender's address - `port`, the port number used to send the packet. @@ -726,7 +726,7 @@ Putting the ESP8266 into deep sleep is out of scope for IO. The `System.deepSlee **`onReadable()`** -Invoked following instantiation if the device was woken from deep sleep. +Invoked following instantiation if the device was woken from deep sleep. #### Data Format The Wakeable Digital IO always uses a data format of `number`. A value of 0 indicates the device did not wake from a deep sleep and a value of 1 indicates that it did wake from a deep sleep. @@ -748,16 +748,16 @@ trace(wakeable.read() ? "Woke from deep sleep\n" : "Hard reset\n"); ## IO Providers IO providers access IO resources that are external to the built-in IO resources. IO providers often use the built-in IO resources to access their external IO resources. The definition of "external" encompasses a wide range of possibilities. -- A separate component on the same board as the microcontroller. +- A separate component on the same board as the microcontroller. Examples of this include GPIO and Analog expanders. These operate over shared-bus protocols like I2C and SPI to provide additional IO pins. -- A separate board physically connected to the board holding the microcontroller. +- A separate board physically connected to the board holding the microcontroller. An example of this is an Arduino connected to a microcontroller over a serial connection as used by the Firmata protocol. -- A separate physical device in close proximity. +- A separate physical device in close proximity. Examples of this include peripherals connected by Bluetooth LE and Decentralized Ambient Synchronization ([DAS](https://blog.moddable.com/blog/das/)) using mDNS over a UDP network connection. -- A separate physical device at a physically remote location. +- A separate physical device at a physically remote location. Examples of this include the Firmata protocol running over a TCP connection and many IoT cloud services operating over protocols including HTTP/REST, MQTT, and WebSocket. @@ -823,7 +823,7 @@ const expander = new Expander({ }); ``` -With the interrupt configured, the `onReadable` callback may be used. +With the interrupt configured, the `onReadable` callback may be used. ```js let buttons = new expander.DigitalBank({ @@ -833,7 +833,7 @@ let buttons = new expander.DigitalBank({ mode: expander.Digital.Input, onReadable(pins) { const result = this.read(); - trace(`Pins ${pins.toString(2)} changed. Buttons now ${result.toString(2)}.`); + trace(`Pins ${pins.toString(2)} changed. Buttons now ${result.toString(2)}.`); } }); ``` @@ -863,7 +863,7 @@ let provider = new CloudProvider({ Note that the MCP23017 expander does not implement the `onReady` callback as it supports a separate component on the same board as the microcontroller accessing it, so there are no significant latencies. -#### Asynchronous I2C +#### Asynchronous I2C All of the IO kinds defined earlier in this document implement asynchronous IO by following the IO Class Pattern directly. It is less obvious how to implement an I2C Master. An implementation of the Firmata Client through the IO Provider API provided a motivation to explore the problem and to find a solution. I2C performs read and write operations with buffers of bytes, much like serial and TCP IO. Serial and TCP (once the connection is established) are essentially peer protocols -- either side of the connection may initiate a write operation at any time. I2C , by contrast, is a master/slave protocol. The slave may only send bytes for the master to read when requested to do so. That requires the master to issue a read request to the slave device to receive data. @@ -898,6 +898,6 @@ From the API perspective, the IO Class Pattern provides clear guidance to the de Perhaps the most interesting perspective is as a script writer using IO classes that follow the pattern. The small API size is easy to remember. This makes it quick and comfortable to work with a range of IO. There are, of course, details that differ from one IO type to another. A digital input is quite different from a UDP socket. Still, these differences are consistent with needs of the IO, not arbitrary differences because their APIs happened to be designed by different individuals at different times with different priorities or different programming style preferences. Overall, this makes it relatively easy to both read and write code that applies the IO Class Pattern. -Based on this exercise of building an implementation of the IO Class Pattern for a microcontroller, the design achieves its goals well. The API meets the needs of low-level script developers to access IO, it is possible to implement efficiently on resource-constrained embedded hardware, and the implementation/porting effort is focused and manageable. +Based on this exercise of building an implementation of the IO Class Pattern for a microcontroller, the design achieves its goals well. The API meets the needs of low-level script developers to access IO, it is possible to implement efficiently on resource-constrained embedded hardware, and the implementation/porting effort is focused and manageable. There is a great deal of work remaining to fully explore the IO Class Pattern. More will be learned from future work, and those lessons will lead to refinements in the design. Areas for future work include ports to other microcontrollers, support for other runtime environments beyond the Moddable SDK, and implementations of other kinds of IO and providers. diff --git a/documentation/network/ble/ble.md b/documentation/network/ble/ble.md index c5676a4d9c..115a210a78 100644 --- a/documentation/network/ble/ble.md +++ b/documentation/network/ble/ble.md @@ -41,7 +41,7 @@ To add the BLE client to a project: /* other includes here */ "$(MODDABLE)/modules/network/ble/manifest_client.json", ], - + To add the BLE server to a project: "include": [ @@ -68,7 +68,7 @@ class Scanner extends BLEClient { trace(completeName + "\n"); } } - + let scanner = new Scanner; ``` @@ -77,7 +77,7 @@ The following BLE server example subclasses `BLEServer` to advertise the device ```javascript import BLEServer from "bleserver"; import {uuid} from "btutils"; - + class HealthThermometerService extends BLEServer { onReady() { this.startAdvertising({ @@ -85,7 +85,7 @@ class HealthThermometerService extends BLEServer { }); } } - + let htm = new HealthThermometerService; ``` @@ -176,7 +176,7 @@ let client = new BLEClient; #### `startScanning([params])` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Object containing scan properties. The `params` object contains the following properties: @@ -186,8 +186,8 @@ The `params` object contains the following properties: | `active` | `boolean` | Set `true` for active scanning, `false` for passive scanning. Default is `true`. | `duplicates` | `boolean` | Set `true` to receive all advertising packets, `false` to filter out multiple advertising packets received from the same peripheral device. Default is `true`. | `filterPolicy` | `number` | Filter policy applied to scan. Default is `GAP.ScanFilterPolicy.NONE` (no filtering). Refer to the [BLE whitelisting](#blewhitelisting) section for details. -| `interval` | `number` | Scan interval value in units of 0.625 ms. Default is `0x50`. -| `window` | `number` | Scan window value in units of 0.625 ms. Default is `0x30`. +| `interval` | `number` | Scan interval value in units of 0.625 ms. Default is `0x50`. +| `window` | `number` | Scan window value in units of 0.625 ms. Default is `0x30`. The `filterPolicy` parameter can be one of the following: @@ -230,10 +230,10 @@ class Scanner extends BLEClient { #### `onDiscovered(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | -The `onDiscovered` callback function is called one or more times for each peripheral device discovered. +The `onDiscovered` callback function is called one or more times for each peripheral device discovered. To connect to a device named "Brian" from the `onDiscovered` callback: @@ -246,7 +246,7 @@ onDiscovered(device) { ``` *** - + #### `stopScanning()` The `stopScanning` function disables scanning for nearby peripherals. @@ -255,7 +255,7 @@ The `stopScanning` function disables scanning for nearby peripherals. #### `connect(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | The `connect` function initiates a connection request between the `BLEClient` and a target peripheral `device`. @@ -274,7 +274,7 @@ onConnected(device) { #### `onConnected(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | The `onConnected` callback function is called when the client connects to a target peripheral `device`. @@ -284,7 +284,7 @@ The `onConnected` callback function is called when the client connects to a targ #### `onDisconnected(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | The `onDisconnected` callback is called when the connection is closed. @@ -340,12 +340,12 @@ An instance of the `Client` class is instantiated by `BLEClient` and provided to | `scanResponse` | `object` | Instance of [Advertisement](#classadvertisement) class containing advertisement and scan response packet values. | `rssi` | `number` | Discovered device signal strength. -### Functions +### Functions #### `exchangeMTU(mtu)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `mtu` | `number` | Requested MTU value | Use the `exchangeMTU ` function to request a higher MTU once the peripheral connection has been established. @@ -354,7 +354,7 @@ Use the `exchangeMTU ` function to request a higher MTU once the peripheral conn #### `onMTUExchanged(device, mtu)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | | `mtu` | `number` | Exchanged MTU value | @@ -382,7 +382,7 @@ Use the `readRSSI` function to read the connected peripheral's signal strength. #### `onRSSI(device, rssi)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | | `rssi` | `number` | Received signal strength | @@ -409,7 +409,7 @@ Use the `discoverAllPrimaryServices` function to discover all the peripheral's G #### `discoverPrimaryService(uuid)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `uuid` | `object` | A [Bytes](#classbytes) object containing the UUID to discover | Use the `discoverPrimaryService` function to discover a single GATT primary service by UUID. @@ -418,7 +418,7 @@ Use the `discoverPrimaryService` function to discover a single GATT primary serv #### `findServiceByUUID(uuid)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `uuid` | `object` | A [Bytes](#classbytes) object containing the Service UUID to find | The `findServiceByUUID` function finds and returns the service identified by `uuid`. This function searches the `services` property array. @@ -428,7 +428,7 @@ The `findServiceByUUID` function finds and returns the service identified by `uu #### `onServices(services)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `services` | `array` | An array of `service` objects, or an empty array if no services are discovered. See the section [Class Service](#classservice) for more information. | The `onServices` callback function is called when service discovery completes. If `findServiceByUUID` was called to find a single service, the `services` array contains the single service found. @@ -444,7 +444,7 @@ onServices(services) { } ``` -To discover a single primary service: +To discover a single primary service: ```javascript const SERVICE_UUID = uuid`0xFF00`; @@ -476,7 +476,7 @@ onDisconnected() { ## Class Service -The `Service` class provides access to a single peripheral GATT service. +The `Service` class provides access to a single peripheral GATT service. ### Properties @@ -498,7 +498,7 @@ Use the `discoverAllCharacteristics()` function to discover all the service char #### `discoverCharacteristic(uuid)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `uuid` | `object` | A [Bytes](#classbytes) object containing the Characteristic UUID to discover | Use the `discoverCharacteristic` function to discover a single service characteristic by UUID. @@ -508,7 +508,7 @@ Use the `discoverCharacteristic` function to discover a single service character #### `findCharacteristicByUUID(uuid)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `uuid` | `object` | A [Bytes](#classbytes) object containing the Characteristic UUID to find | The `findCharacteristicByUUID` function finds and returns the characteristic identified by `uuid`. This function searches the `characteristics` property array. @@ -518,7 +518,7 @@ The `findCharacteristicByUUID` function finds and returns the characteristic ide #### `onCharacteristics(characteristics)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristics` | `array` | An array of `characteristic` objects, or an empty array if no characteristics are discovered. See the section [Class Characteristic](#classcharacteristic) for more information. | The `onCharacteristics` callback function is called when characteristic discovery completes. If `findCharacteristicByUUID` was called to find a single characteristic, the `characteristics` array contains the single characteristic found. @@ -587,7 +587,7 @@ Use the `discoverAllDescriptors` function to discover all the characteristic's d #### `onDescriptors(descriptors)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `descriptors` | `array` | An array of `descriptor` objects, or an empty array if no descriptors are discovered. See the section [Class Descriptor](#classdescriptor) for more information. | The `onDescriptors` callback function is called when descriptor discovery completes. @@ -620,7 +620,7 @@ Use the `enableNotifications` function to enable characteristic value change not #### `onCharacteristicNotificationEnabled(characteristic)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | A `characteristic` object. | The `onCharacteristicNotificationEnabled` callback function is called when notifications have been enabled for the `characteristic`. @@ -635,7 +635,7 @@ Use the `disableNotifications` function to disable characteristic value change n #### `onCharacteristicNotificationDisabled(characteristic)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | A `characteristic` object. | The `onCharacteristicNotificationDisabled` callback function is called when notifications have been disabled for the `characteristic`. @@ -645,7 +645,7 @@ The `onCharacteristicNotificationDisabled` callback function is called when noti #### `onCharacteristicNotification(characteristic, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | A `characteristic` object. | | `value` | `varies` | The `characteristic` value. The value is automatically converted to the `type` defined in the service JSON, when available. Otherwise `value` is an `ArrayBuffer`. | @@ -680,7 +680,7 @@ onCharacteristicNotification(characteristic, value) { Use the `readValue` function to read a characteristic value on demand. | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `auth` | `number` | Optional `SM.Authorization` applied to the read request. | The `Authorization` object contains the following properties: @@ -698,7 +698,7 @@ The `Authorization` object contains the following properties: #### `onCharacteristicValue(characteristic, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | A `characteristic` object. | | `value` | `varies` | The `characteristic` value read. The value `type` is defined by the service JSON, when available. Otherwise `value` is an `ArrayBuffer`. | @@ -732,7 +732,7 @@ onCharacteristicValue(characteristic, value) { #### `writeWithoutResponse(value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `value` | `varies` | The `characteristic` value to write. The value `type` is defined by the service JSON, when available. Otherwise `value` is an `ArrayBuffer` or `String`. | Use the `writeWithoutResponse` function to write a characteristic value on demand. @@ -779,7 +779,7 @@ The `Descriptor` class provides access to a single characteristic descriptor. Use the `readValue` function to read a descriptor value on demand. | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `auth` | `number` | Optional `SM.Authorization` applied to the read request. | The `Authorization` object contains the following properties: @@ -797,7 +797,7 @@ The `Authorization` object contains the following properties: #### `onDescriptorValue(descriptor, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `descriptor ` | `object` | A `descriptor` object. | | `value` | `varies` | The `descriptor` value read. The value `type` is defined by the service JSON, when available. Otherwise `value` is an `ArrayBuffer`. | @@ -822,7 +822,7 @@ onDescriptorValue(descriptor, value) { #### `writeValue(value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `value` | `varies` | The `descriptor` value to write. The value `type` is defined by the service JSON, when available. Otherwise `value` is an `ArrayBuffer` or `String`. | Use the `writeValue` function to write a descriptor value. @@ -840,7 +840,7 @@ onDescriptors(descriptors) { } } ``` - + > **Note:** The `Characteristic` `enableNotifications` convenience function is typically used for this purpose, though writing the CCCD descriptor directly provides the same net result. @@ -866,11 +866,11 @@ The `Advertisement` class provides accessor functions to read common advertiseme Use the `findIndex` function to find the index of a specific advertisement data type in the raw advertisement data bytes. | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `type` | `number` | The `GAP.ADType` to search for. | | `index` | `number` | The optional starting index to search from. Defaults to 0. | -### Examples +### Examples To identify an advertised device with the complete name "Zip": @@ -888,8 +888,8 @@ To identify a [Blue Maestro Environment Monitor](https://www.bluemaestro.com/pro ```javascript onDiscovered(device) { let manufacturerSpecific = device.scanResponse.manufacturerSpecific; - const TempoManufacturerID = 307; - + const TempoManufacturerID = 307; + // If this is a Tempo device... if (manufacturerSpecific && (TempoManufacturerID == manufacturerSpecific.identifier)) { let data = manufacturerSpecific.data; @@ -919,13 +919,13 @@ onDiscovered(device) { ## Class Bytes The private `Bytes` class extends `ArrayBuffer`. Applications typically use the provided `uuid` and `address` tagged templates to create a `Bytes` instance from hex strings. - + #### Constructor Description #### `Bytes(bytes [,littleEndian])` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `bytes` | `object` or `string` | The ArrayBuffer `bytes` to set. The bytes can be a String or ArrayBuffer. | | `littleEndian` | `boolean` | When set `true` the contents of the ArrayBuffer are stored in reverse order. Default is `false`.| ### Functions @@ -954,11 +954,11 @@ const CHARACTERISTIC_RX_UUID = uuid`6E400002-B5A3-F393-E0A9-E50E24DCCA9E`; #### `equals(buffer)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `buffer` | `object` | The `Bytes` instance to compare. | The `equals` function returns `true` if the instance ArrayBuffer data equals the data contained in `buffer`. - + ```javascript import {uuid} from "btutils"; @@ -1207,7 +1207,7 @@ import {address} from "btutils"; this.startAdvertising({ connectable: false, advertisingData: {flags: 5, completeName: "Moddable HRS"}, - scanResponseData: {shortName: "Moddable", randomAddress: address`00:11:22:33:44:55`} + scanResponseData: {shortName: "Moddable", randomAddress: address`00:11:22:33:44:55`} }); ``` @@ -1245,7 +1245,7 @@ onConnected(device) { #### `notifyValue(characteristic, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | The `characteristic` object to notify. | | `value` | `varies` | The `characteristic` notification value. The value is automatically converted from the `type` defined in the service JSON. | @@ -1271,21 +1271,21 @@ startNotifications(characteristic) { The `onAdvertisementSent` callback function is called after each advertising data packet sent, when a server enables advertisement notifications from the `startAdvertising()` function. > Note: The `onAdvertisementSent` callback is only implemented for nRF52 devices. - + *** #### `onCharacteristicNotifyEnabled(characteristic)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | The `characteristic` object with notifications enabled. The `onCharacteristicNotifyEnabled` callback function is called when a client enables notifications on the `characteristic`. - + *** #### `onCharacteristicWritten(characteristic, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic` | `object` | The `characteristic` object written. | `value` | `varies` | The value written. The value is automatically converted to the `type` defined in the service JSON. @@ -1321,7 +1321,7 @@ onCharacteristicWritten(characteristic, value) { #### `onCharacteristicRead(characteristic)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `characteristic ` | `object` | The characteristic object being read. The `characteristic` object contains the following properties: @@ -1349,7 +1349,7 @@ onCharacteristicRead(characteristic) { *** #### `disconnect()` -Use the `disconnect` function to terminate the BLE client connection. +Use the `disconnect` function to terminate the BLE client connection. ```javascript import {address} from "btutils"; @@ -1371,7 +1371,7 @@ onDisconnected(device) { #### `onConnected(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | The `onConnected` callback function is called when a client connects to the `BLEServer`. @@ -1380,7 +1380,7 @@ The `onConnected` callback function is called when a client connects to the `BLE #### `onDisconnected(device)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `device` | `object` | A `device` object. See the section [Class Client](#classclient) for more information. | The `onDisconnected` callback function is called when the client connection is closed. @@ -1438,7 +1438,7 @@ The following is an example of JSON corresponding to a Bluetooth [Battery Servic } } } - + The service is defined as follows: * The service UUID is 0x180F @@ -1483,7 +1483,7 @@ onReady() { #### `deleteBonding(address, addressType)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `address` | `object` | `ArrayBuffer` containing peer device Bluetooth address | `addressType` | `number` | Peer device Bluetooth address type. Refer to `GAP.AddressType` for supported address types. @@ -1517,7 +1517,7 @@ onReady() { #### `passkeyInput(address, value)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `address` | `object` | `ArrayBuffer` containing peer device Bluetooth address | `value` | `number` | passkey value input @@ -1535,7 +1535,7 @@ onPasskeyInput(params) { #### `passkeyReply(address, result)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `address` | `object` | `ArrayBuffer` containing peer device Bluetooth address | `result` | `boolean` | Set `true` to confirm passkey value, `false` otherwise @@ -1553,7 +1553,7 @@ onPasskeyConfirm(params) { #### `onSecurityParameters(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Device security properties applied. The `onSecurityParameters` callback is called after the device security requirements and I/O capabilities have been set. @@ -1574,7 +1574,7 @@ onSecurityParameters() { #### `onAuthenticated(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Properties associated with the authentication procedure. The `params` object contains the following properties: @@ -1597,7 +1597,7 @@ onAuthenticated(params) { #### `onPasskeyConfirm(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Properties associated with the passkey confirmation. The `params` object contains the following properties: @@ -1612,7 +1612,7 @@ The `onPasskeyConfirm` callback is called when the user needs to confirm a passk ```javascript onPasskeyConfirm(params) { trace(`confirm passkey: ${params.passkey}\n`); - + // passkey is valid this.passkeyReply(params.address, true); } @@ -1622,7 +1622,7 @@ onPasskeyConfirm(params) { #### `onPasskeyDisplay(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Properties associated with the passkey display. The `params` object contains the following properties: @@ -1646,7 +1646,7 @@ onPasskeyDisplay(params) { #### `onPasskeyInput(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Properties associated with the passkey input. The `params` object contains the following properties: @@ -1670,7 +1670,7 @@ onPasskeyInput(params) { #### `onPasskeyRequested(params)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `params` | `object` | Properties associated with the passkey to request. The `params` object contains the following properties: @@ -1713,7 +1713,7 @@ import GAPWhitelist from "gapwhitelist"; #### `add(address [,addressType])` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `address` | `string` or `object` | The peer address to whitelist. | `addressType` | `number` | Optional peer address type. Defaults to `GAP.AddressType.PUBLIC`. @@ -1750,7 +1750,7 @@ onDisconnected() { #### `remove(address [,addressType])` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `address` | `string` or `object` | The peer address to whitelist. | `addressType` | `number` | Optional peer address type. Defaults to `GAP.AddressType.PUBLIC`. @@ -1790,9 +1790,9 @@ After building the BLE archive, the archive is linked to the native app hosted i initMcu(); initBoard(); initApp(); - + xs_setup(); - + while (1) { xs_loop(); } @@ -1802,7 +1802,7 @@ BLE apps require additional stack and heap. We've been able to run the Moddable __STACK_SIZE=0x2000 __HEAP_SIZE=0xA000 - + Simplicity Studio includes a **BLE GATT Configurator** to define BLE services. Moddable apps define BLE services in JSON files and hence don't use the `gatt_db.c` and `gatt_db.h` files generated by the configurator tool. These two files must be removed from the Simplicity Studio project. @@ -1840,5 +1840,5 @@ The Moddable SDK includes many BLE client and server example apps to build from. | [heart-rate-server](../../../examples/network/ble/heart-rate-server) | Implements the Bluetooth [Heart Rate Service](https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.heart_rate.xml). | [security-server](../../../examples/network/ble/security-server) | Demonstrates how to implement a secure health thermometer BLE server using SMP. The `security-server` can connect to the [security-client](../../../examples/network/ble/security-client) app. | [uri-beacon](../../../examples/network/ble/uri-beacon) | Implements a [UriBeacon](https://github.com/google/uribeacon/tree/uribeacon-final/specification) compatible with Google's [Physical Web](https://github.com/google/physical-web) discovery service. -| [wifi-connection-server](../../../examples/network/ble/wifi-connection-server) | Deploys a BLE WiFi connection service on ESP32. The connection service allows BLE clients to connect the BLE device to a WiFi access point, by writing the SSID and password characteristics. +| [wifi-connection-server](../../../examples/network/ble/wifi-connection-server) | Deploys a BLE WiFi connection service on ESP32. The connection service allows BLE clients to connect the BLE device to a WiFi access point, by writing the SSID and password characteristics. | [uart-server](../../../examples/network/ble/uart-server) | Shows how implement a Nordic UART Service server. The `uart-server` can connect to the [uart-client](../../../examples/network/ble/uart-client) app. diff --git a/documentation/network/ethernet.md b/documentation/network/ethernet.md index e2f0f39096..2f5a5dfa74 100644 --- a/documentation/network/ethernet.md +++ b/documentation/network/ethernet.md @@ -6,7 +6,7 @@ Revised: November 16, 2021 The Moddable SDK supports Ethernet for the ESP32. Ethernet support is an extension to our [network support](./network.md), which includes support for Wi-Fi and protocols like HTTP/HTTPS, MQTT, WebSockets, DNS, and mDNS. Most of the [networking examples](../../examples/network) in the Moddable SDK enable Wi-Fi by default, but examples that work with Wi-Fi can easily be made to use Ethernet instead. -This document provides information about how to enable Ethernet in applications, details of the JavaScript API used to establish and monitor an Ethernet connection, and wiring instructions for a compatible Ethernet breakout board. +This document provides information about how to enable Ethernet in applications, details of the JavaScript API used to establish and monitor an Ethernet connection, and wiring instructions for a compatible Ethernet breakout board. ## Table of Contents @@ -124,7 +124,7 @@ let monitor = new Ethernet((msg) => { // Got IP address break; } -}); +}); ``` ### `close()` @@ -134,7 +134,7 @@ The `close` method closes the connection between the `Ethernet` instance and the ```js let monitor = new Ethernet((msg) => { trace(`Ethernet msg: ${msg}\n`); -}); +}); monitor.close(); ``` @@ -152,7 +152,7 @@ let monitor = new Ethernet((msg) => { case Ethernet.connected: trace(`Physical link established. Waiting for IP address.\n`); break; - + case Ethernet.gotIP: let ip = Net.get("IP", "ethernet"); trace(`Ethernet connected. IP address ${ip}\n`); @@ -162,7 +162,7 @@ let monitor = new Ethernet((msg) => { trace(`Ethernet connection lost.\n`); break; } -}); +}); ``` ### Example: Get MAC address of Ethernet device diff --git a/documentation/network/network.md b/documentation/network/network.md index f87280a217..e0e14660a9 100644 --- a/documentation/network/network.md +++ b/documentation/network/network.md @@ -9,7 +9,7 @@ Revised: March 8, 2022 * HTTP * [Request](#http-request) * [Server](#http-server) -* WebSocket +* WebSocket * [Client](#websocket-client) * [Server](#websocket-server) * [Net](#net) @@ -186,7 +186,7 @@ For a RAW socket, the first parameter is IP address to transmit the packet to. T socket.write("1.2.3.4", packet); ``` -It is more efficient to make a single `write` call with several parameters instead of multiple calls to `write`. +It is more efficient to make a single `write` call with several parameters instead of multiple calls to `write`. *** @@ -390,7 +390,7 @@ The user of the `Request` object receives status information through the callbac | `message` | `Request.` | Description | | :---: | :---: | :--- | -|-2 | `error` | +|-2 | `error` | | 0 | `requestFragment` | Get request body fragment. This callback is only received if the `body` property in the dictionary is set to `true`. When called, `val1` is the maximum number of bytes that can be transmitted. Return either a `String` or `ArrayBuffer` containing the next fragment of the request body. Return `undefined` when there are no more fragments. | 1 | `status` | Response status received with status code. This callback is invoked when the HTTP response status line is successfully received. When called, `val1` is the HTTP status code (e.g. 200 for OK). | 2 | `header` | One header received. The callback is called for each header in the response. When called, `val1` is the header name in lowercase letters (e.g. `connection`) and `val2` is the header value (e.g. `close`). @@ -414,7 +414,7 @@ import {Server} from "http" ### `constructor(dictionary)` -A new HTTP server is configured using a dictionary of properties. The dictionary is a super-set of the `Socket` dictionary. +A new HTTP server is configured using a dictionary of properties. The dictionary is a super-set of the `Socket` dictionary. To open an HTTP server, on the default port (80): @@ -503,7 +503,7 @@ The following example implements an HTTP server that responds to requests with a switch (message) { case 8: // prepare response body return {headers: ["Content-type", "text/plain"], body: true}; - + case 9: // provide response body fragment let i = Math.round(Math.random() * 20); if (0 == i) @@ -560,7 +560,7 @@ import {File} from "file"; case 4: // prepare for request body return true; // provide request body in fragments - + case 5: // request body fragment this.file.write(this.read(ArrayBuffer)); break; @@ -696,7 +696,7 @@ ws.close(); ### `attach(socket)` -The `attach` function creates a new incoming WebSockets connection from the provided socket. The server issues the `Server.connect` callback and then performs the WebSockets handshake. The status line has been read from the socket, but none of the HTTP headers have been read as these are required to complete the handshake. +The `attach` function creates a new incoming WebSockets connection from the provided socket. The server issues the `Server.connect` callback and then performs the WebSockets handshake. The status line has been read from the socket, but none of the HTTP headers have been read as these are required to complete the handshake. See the [httpserverwithwebsockets](../../examples/network/http/httpserverwithwebsockets/main.js) for an example of sharing a single listener socket between the HTTP and WebSockets servers. @@ -732,7 +732,7 @@ The `get` function returns properties of the active network connection. The following properties are available: -| Property | Description | +| Property | Description | | :---: | :--- | | `IP` | The IP address of the network connection as a `String`, e.g. "10.0.1.4". These may be IPv4 or IPv6 addresses. | `MAC` | The MAC address of the device as a `String`, e.g. "A4:D1:8C:DB:C0:20" @@ -747,7 +747,7 @@ The following properties are available: trace(`Connected to Wi-Fi access point: ${Net.get("SSID")}\n`); ``` -For a device operating as both a Wi-Fi station (client) and a Wi-Fi access point, the static `get` method accepts an optional second argument to indicate if the request is for the station or access point interface. The interface accepts values of `"station"` and `"ap"`. It is used for the `IP` and `MAC` properties. +For a device operating as both a Wi-Fi station (client) and a Wi-Fi access point, the static `get` method accepts an optional second argument to indicate if the request is for the station or access point interface. The interface accepts values of `"station"` and `"ap"`. It is used for the `IP` and `MAC` properties. On ESP32, the optional second argument can also be used to explicitly request information about the Ethernet interface by providing the value `"ethernet"`. @@ -788,7 +788,7 @@ import WiFi from "wifi"; ### `constructor(dictionary, callback)` -The `WiFi` constructor takes a single argument, a dictionary of initialization parameters. The constructor begins the process of establishing a connection. +The `WiFi` constructor takes a single argument, a dictionary of initialization parameters. The constructor begins the process of establishing a connection. The dictionary always contains the required `ssid` property with the name of the base station to connect to. The optional `password` property is included when the base station requires a password. When the optional `bssid` property is included, it may accelerate connecting to Wi-Fi on device targets that support it. @@ -826,7 +826,7 @@ monitor.close(); ### `static scan(dictionary, callback)` -The `scan` static function initiates a scan for available Wi-Fi access points. +The `scan` static function initiates a scan for available Wi-Fi access points. The dictionary parameter supports two optional properties: @@ -959,10 +959,10 @@ The DNS module contains constants that are useful when implementing code that in ```js import DNS from "dns"; ``` - + - `DNS.RR` contains constants for resource record types, such as `DNS.RR.PTR`. - `DNS.OPCODE` contains values for `DNS.OPCODE.QUERY` and `DNS.OPCODE.UPDATE`. -- `DNS.CLASS` contains values for `DNS.CLASS.IN`, `DNS.CLASS.NONE`, and `DNS.CLASS.ANY`. +- `DNS.CLASS` contains values for `DNS.CLASS.IN`, `DNS.CLASS.NONE`, and `DNS.CLASS.ANY`. - `DNS.SECTION` contains values that include `DNS.QUESTION` and `DNS.ANSWER`. @@ -988,12 +988,12 @@ No validation is performed by the constructor. Errors, if any, are reported when *** ### `questions(index)` -Returns the question resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of question records in the packet. +Returns the question resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of question records in the packet. *** ### `answers(index)` -Returns the answer resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of answer records in the packet. +Returns the answer resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of answer records in the packet. *** @@ -1003,7 +1003,7 @@ Returns the authority resource record corresponding to the index argument. Indic *** ### `additionals(index)` -Returns the additional resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of additional records in the packet. +Returns the additional resource record corresponding to the index argument. Indices are numbered from 0. Returns `null` if index is greater than number of additional records in the packet. *** @@ -1026,7 +1026,7 @@ The parser instance has properties for the `id` and `flags` fields in the DNS pa let id = packet.id; let flags = packet.flags; ``` - + *** ### Example: Determining the number of records @@ -1069,7 +1069,7 @@ The DNS `Serializer` constructor accepts a dictionary with properties to configu | Property | Default Value | Description | | :---: | :---: | :--- | -| `opcode` | `DNS.OPCODE.QUERY` | The numeric value of the `opcode` header field +| `opcode` | `DNS.OPCODE.QUERY` | The numeric value of the `opcode` header field | `query` | `true` | A boolean that indicates whether this packet contains a query or response | `authoritative` | `false` | A boolean indicating the value of the `authoritative` bit in the header | `id` | 0 | A numeric value for the ID field @@ -1095,7 +1095,7 @@ The optional `data` argument is used to build the resource data portion of the r | `A` | A string containing the IP address. | `NSEC` | A dictionary with two keys. The first is `next` containing a string with the next hostname value. The second is a Uint8Array containing the bit-mask. | `PTR` | A string with the PTR value. -| `SRV` | A dictionary with four keys. The `priority`, `weight`, and `port` fields are numbers with the value of the corresponding field. The `target` property is a string containing the name of the target. +| `SRV` | A dictionary with four keys. The `priority`, `weight`, and `port` fields are numbers with the value of the corresponding field. The `target` property is a string containing the name of the target. | `TXT` | A dictionary of key / value pairs for the TXT record. The property name is the key. Only string values are supported at this time. *** @@ -1168,7 +1168,7 @@ new DNSServer((message, value) => { }) ``` -> **Note:**: This example expects to be run on a Wi-Fi connection in access point mode. It passes "ap" for the interface argument to `Net.get` to retrieve the IP address for access point. +> **Note:**: This example expects to be run on a Wi-Fi connection in access point mode. It passes "ap" for the interface argument to `Net.get` to retrieve the IP address for access point. ### Example: DNS server for a single host name @@ -1187,7 +1187,7 @@ new DNSServer((message, value) => { ## class MDNS - **Source code:** [mdns](../../modules/network/mdns) -- **Relevant Examples:** [discoverhttp](../../examples/network/mdns/discoverhttp), [httpserver](../../examples/network/mdns/httpserver), [ntpclient](../../examples/network/mdns/ntpclient), [ntpservice](../../examples/network/mdns/ntpservice), +- **Relevant Examples:** [discoverhttp](../../examples/network/mdns/discoverhttp), [httpserver](../../examples/network/mdns/httpserver), [ntpclient](../../examples/network/mdns/ntpclient), [ntpservice](../../examples/network/mdns/ntpservice), The `MDNS` class implements services for working with [Multicast DNS](https://tools.ietf.org/html/rfc6762) discovery and services. It includes claiming `.local` names, advertising mDNS service availability, and scanning for available mDNS services. @@ -1216,7 +1216,7 @@ const mdns = new MDNS({hostName: "mydevice"}); ``` The claiming process takes some time, usually under one second. Claiming the name may not succeed because the name may already be in use. An optional callback function provides status on the claim: - + ```js const mdns = new MDNS({hostName: "mydevice"}, function(message, value) { switch (message) { @@ -1289,7 +1289,7 @@ let service = mdns.services[0]; service.txt["value"] = 123; mdns.update(service); ``` - + *** ### `remove(service)` or `remove(serviceType)` @@ -1466,7 +1466,7 @@ Use the `unsubscribe` method to unsubscribe to a topic. mqtt.unsubscribe("test/string"); ``` -### `onMessage(topic, data)` +### `onMessage(topic, data)` The `onMessage` callback is invoked when a message is received for any topic that your client has subscribed to. The `topic` argument is the name of the topic and the `data` argument is the complete message. diff --git a/documentation/network/securesocket.md b/documentation/network/securesocket.md index 48fce34511..9505a791f0 100644 --- a/documentation/network/securesocket.md +++ b/documentation/network/securesocket.md @@ -51,7 +51,7 @@ In the following example, the TLS socket is created with support for version `0x ```js let socket = new SecureSocket({ - host: "www.example.com", + host: "www.example.com", port: 443, secure: { protocolVersion: 0x303 @@ -68,8 +68,8 @@ The HTTP `Client` class accepts an optional `Socket` property in the dictionary let request = new Request({ host: "www.howsmyssl.com", path: "/", - response: String, - Socket: SecureSocket, + response: String, + Socket: SecureSocket, port: 443, secure: { trace: true, @@ -85,9 +85,9 @@ The WebSocket `Client` class accepts an optional `Socket` property in the dictio ```js let ws = new Client({ - host: "echo.websocket.org", + host: "echo.websocket.org", port: 443, - Socket: SecureSocket, + Socket: SecureSocket, secure: { protocolVersion: 0x302 } @@ -150,10 +150,10 @@ As an alternative to the certificate store, you can put the certificates needed ```js let request = new Request({ - host: "www.howsmyssl.com", + host: "www.howsmyssl.com", path: "/", - response: String, - Socket: SecureSocket, + response: String, + Socket: SecureSocket, port: 443, secure: { certificate: new Resource("ca109.der") @@ -170,19 +170,19 @@ let request = new Request({ ... secure: { certificate: new Resource("mycert.der") - } + } }); ``` #### Converting PEM to DER -The `SecureSocket` implementation requires certificates to be provided in DER (binary) format. If you have a certificate in PEM (a Base64 encoded) format, you need to convert it to DER. +The `SecureSocket` implementation requires certificates to be provided in DER (binary) format. If you have a certificate in PEM (a Base64 encoded) format, you need to convert it to DER. Whenever possible, convert the PEM file to DER format before adding it to your project. There are many tools that can perform the conversion. A reliable choice is `openssl`. The following command line works for many certificates (substitute your PEM file path for `data.pem` and the desired output file path for `data.der`): ``` openssl x509 -inform pem -in data.pem -out data.der -outform der -``` +``` Sometimes there is no choices but to convert the PEM to DER at runtime. For example, during provisioning you might receive a certificate in PEM format from a service, and later you need to use that certificate to establish a TLS connection. The Moddable SDK provides the [`pemtoDER`](../crypt/crypt.md#transform-pemToDER) and [`privateKeyToPrivateKeyInfo`](../crypt/crypt.md#transform-privateKeyToPrivateKeyInfo) functions for these situations. These functions are part of the Crypt `Transform` class. diff --git a/documentation/network/webthings.md b/documentation/network/webthings.md index ce4938e24e..390e1e0387 100644 --- a/documentation/network/webthings.md +++ b/documentation/network/webthings.md @@ -14,7 +14,7 @@ Revised: August 28, 2019 ## Introduction -The Web Thing API is part of the [Project Things](https://iot.mozilla.org) initiative by Mozilla to define open communication protocols between IoT products. The Web Thing API is a protocol built using JSON, HTTP, and mDNS. It is related to the larger [Web of Things](https://www.w3.org/WoT/) effort of W3C. The IoT team at Mozilla created a home gateway that works with IoT products that implement the Web Thing API protocol. Mozilla also provides embedded device APIs to make it easier to create products that support the Web Thing API. All this work is in development, so it is not ready incorporate into products. +The Web Thing API is part of the [Project Things](https://iot.mozilla.org) initiative by Mozilla to define open communication protocols between IoT products. The Web Thing API is a protocol built using JSON, HTTP, and mDNS. It is related to the larger [Web of Things](https://www.w3.org/WoT/) effort of W3C. The IoT team at Mozilla created a home gateway that works with IoT products that implement the Web Thing API protocol. Mozilla also provides embedded device APIs to make it easier to create products that support the Web Thing API. All this work is in development, so it is not ready incorporate into products. In the goals of Mozilla's Web Thing API effort we hear echoes of Moddable's own goals of creating an open environment of IoT products that put the user in control. Consequently, at Moddable we have begun experimenting with the Web Thing API. One result of that work is a set of simple JavaScript classes for building devices compatible with the Web Thing API. The classes have been successfully used on ESP8266 and ESP32 hardware with the Mozilla gateway. @@ -31,7 +31,7 @@ The Web of Things [gateway software](https://iot.mozilla.org/gateway/) is availa The Moddable SDK repository on GitHub contains the [WebThings implementation](https://github.com/Moddable-OpenSource/moddable/tree/public/modules/network/webthings) and several [example device implementations](https://github.com/Moddable-OpenSource/moddable/tree/public/examples/network/webthings). -This documentation describes how to implement a `WebThing` subclass to be used with the `WebThings` host. The `WebThing` class is a base class to be subclassed by specific implementations. It contains no device specific capabilities. +This documentation describes how to implement a `WebThing` subclass to be used with the `WebThings` host. The `WebThing` class is a base class to be subclassed by specific implementations. It contains no device specific capabilities. ### Implementing a Light using the WebThing class @@ -168,14 +168,14 @@ The `add` function registers a subclass of `WebThing`. The constructor argument In this example, `OnOffLight` is the class defined in the "Implementing a Light using the WebThing class" section above. ```js -things.add(OnOffLight); +things.add(OnOffLight); ``` *** ## class WebThing -The `WebThing` class is subclassed to create implementations of specific Web Things. +The `WebThing` class is subclassed to create implementations of specific Web Things. ```js import {WebThing} from "webthings"; diff --git a/documentation/pins/audioout.md b/documentation/pins/audioout.md index 353b397352..ad96a05071 100644 --- a/documentation/pins/audioout.md +++ b/documentation/pins/audioout.md @@ -93,7 +93,7 @@ This is done by using the ability to repeat a sample an infinite number of times audio.enqueue(0, AudioOut.Samples, aSample, 1, aSample.attackStart, aSample.attackCount); audio.enqueue(0, AudioOut.Samples, aSample, Infinity, aSample.sustainStart, aSample.sustainCount); ``` - + When it is time to end playback of the sample, enqueue the decay section. This will terminate the enqueue sustain section when it completes the current repetition: ```js @@ -101,7 +101,7 @@ audio.enqueue(0, AudioOut.Samples, aSample, 1, aSample.decayStart, aSample.decay ``` ### constructor(dictionary) -The constructor accepts a dictionary to configure the audio output. +The constructor accepts a dictionary to configure the audio output. ```js let audio = new AudioOut({sampleRate: 11025, bitsPerSample: 16, numChannels: 2, streams: 3}); @@ -132,7 +132,7 @@ audio.start(); ``` ### stop() -Call the `stop` function to immediately suspend audio playback. +Call the `stop` function to immediately suspend audio playback. ```js audio.stop(); @@ -174,12 +174,12 @@ audio.enqueue(0, AudioOut.Samples, bufferTwo, Infinity); ``` If the repeat count is `Infinity`, the buffer is repeated until the audio out instance is closed, the streaming is flushed, or another buffer of audio is enqueued. In the final case, the currently playing buffer plays to completion, and then the following buffer is played. - + A subset of the samples in the buffer may be selected for playback by using the optional `offset` and `count` parameters. Both parameters are in units of samples, not bytes. The `offset` parameter indicates the number of samples into the buffer to begin playback. If the `count` parameter is not provided, playback proceeds to the end of the buffer. It the `count` parameter is provided, only the number of samples it specifies are played. #### Enqueuing tones and silence -To `enqueue` a tone, provide the frequency and number of samples. The square wave will be generated. The following queues 8000 samples of a 440 Hz A natural. Pass `Infinty` for the sample count to play the tone until `flush`, `stop`, or `close`. +To `enqueue` a tone, provide the frequency and number of samples. The square wave will be generated. The following queues 8000 samples of a 440 Hz A natural. Pass `Infinty` for the sample count to play the tone until `flush`, `stop`, or `close`. ```js audio.enqueue(0, AudioOut.Tone, 440, 8000); diff --git a/documentation/pins/pins.md b/documentation/pins/pins.md index 56f0f0b254..56f70269b5 100644 --- a/documentation/pins/pins.md +++ b/documentation/pins/pins.md @@ -50,7 +50,7 @@ To open a GPIO pin on a specific port, use the Digital constructor with the opti ```js let blink = 1; let led = new Digital("gpioPortName", 5, Digital.Output); - + Timer.repeat(id => { blink = blink ^ 1; led.write(blink); @@ -91,7 +91,7 @@ The following example configures pin 5 as an output and then blinks it one per s ```js let blink = 1; - + Timer.repeat(id => { blink = blink ^ 1; Digital.write(5, blink); @@ -192,7 +192,7 @@ let monitor = new Monitor({pin: 0, port: "B", mode: Digital.Input, edge: Monitor ### `onChanged()` callback -A script must install an `onChanged` callback on the instance to be invoked with the specified edge events occur. +A script must install an `onChanged` callback on the instance to be invoked with the specified edge events occur. ```js monitor.onChanged = function() { @@ -285,7 +285,7 @@ The `Analog` class provides access to the analog input pins. ```js import Analog from "pins/analog"; ``` - + ### `constructor(dictionary)` The `Analog` dictionary requires a `pin` property. On platforms supporting wake-up from deep sleep on analog input triggers, the `onWake`, `wakeCrossing`, and `wakeValue` properties are additionally required to configure the analog input as a wake-up trigger. Refer to the `onWake() callback` section below for further details. @@ -297,17 +297,17 @@ let analog = new Analog({ pin: 5 }); trace(`Analog value is ${analog.read()}\n`); ``` -**Note**: The nRF52 platform currently only supports the constructor and instance read function. On all other platforms, the Analog class provides only static functions. +**Note**: The nRF52 platform currently only supports the constructor and instance read function. On all other platforms, the Analog class provides only static functions. ### `static read(pin)` -The `read` function samples the value of the specified pin, returning a value from 0 to 1023. +The `read` function samples the value of the specified pin, returning a value from 0 to 1023. Pin numbers are device dependent: - The ESP8266 NodeMCU board has a single analog input pin, analog pin number 0. - On the ESP32, use the analog channel number, not the associated GPIO number. You can find GPIO number to analog channel mappings for ESP32 and ESP32-S2 in the [ESP-IDF ADC documentation](https://docs.espressif.com/projects/esp-idf/en/v4.2-beta1/esp32/api-reference/peripherals/adc.html#_CPPv414adc1_channel_t). Only ADC1 is supported on the ESP32. -The following example samples an analog temperature sensor, converting the result to celsius degrees. +The following example samples an analog temperature sensor, converting the result to celsius degrees. let temperature = (Analog.read(0) / 1023) * 330 - 50; trace(`Temperature is ${temperature} degrees celsius\n`); @@ -361,7 +361,7 @@ import PWM from "pins/pwm"; ### `constructor(dictionary)` -The PWM constructor takes a dictionary which contains the pin number to use. Pin numbers are device dependent. +The PWM constructor takes a dictionary which contains the pin number to use. Pin numbers are device dependent. The dictionary may optionally contain a `port` property. If the port is not provided, the default port (`NULL`) is used. @@ -452,19 +452,19 @@ sensor.read(3, bytes.buffer); ### `write(...value [, stop])` -The `write` function writes up to 40 bytes to the target device. The write function accepts multiple arguments, concatenating them together to send to the device. The values may be numbers, which are transmitted as bytes, Arrays, TypedArrays, and strings (which are transmitted as UTF-8 encoded text bytes). +The `write` function writes up to 40 bytes to the target device. The write function accepts multiple arguments, concatenating them together to send to the device. The values may be numbers, which are transmitted as bytes, Arrays, TypedArrays, and strings (which are transmitted as UTF-8 encoded text bytes). The `write` function accepts an optional final boolean argument, `stop`, which indicates if a stop condition should be sent when the write is complete. If the final argument is not a boolean value, a stop condition is sent. ```js let sensor = new I2C({address: 0x48}); -sensor.write(0); +sensor.write(0); ``` *** ### Example: Reading an I2C temperature sensor -The following example instantiates an I2C connection to a [temperature sensor](https://www.sparkfun.com/products/11931) with address 0x48 connected to pins 4 and 5. +The following example instantiates an I2C connection to a [temperature sensor](https://www.sparkfun.com/products/11931) with address 0x48 connected to pins 4 and 5. ```js let sensor = new I2C({sda: 5, scl: 4, address: 0x48}); @@ -482,7 +482,7 @@ value *= 0.0625; trace(`Celsius temperature: ${value}\n`); ``` - + *** @@ -546,7 +546,7 @@ The following example establishes an SMBus connection to a [triple axis magnetom ```js let sensor = new SMBus({address: 0x1E}); - + let id = sensor.readBlock(10, 3); id = String.fromCharCode(id[0]) + String.fromCharCode(id[1]) + String.fromCharCode(id[2]); if ("H43" != id) @@ -557,7 +557,7 @@ sensor.writeByte(2, 0); // continuous measurement mode *** - + ## class Servo @@ -569,7 +569,7 @@ The `Servo` class uses digital pins to control servo motors. The API is designed ```js import Servo from "pins/servo"; ``` - + ### `constructor(dictionary)` The Servo constructor takes a dictionary. The `pin` property is required, and specifies the digital pin to use. The `min` and `max` properties are optional, and specify the range of the pulse duration in microseconds. @@ -595,7 +595,7 @@ servo.write(45); ### `writeMicroseconds(us)` -The `writeMicroseconds` call sets the duration of the pulse width in microseconds. The value provided is pinned by the `min` and `max` values. +The `writeMicroseconds` call sets the duration of the pulse width in microseconds. The value provided is pinned by the `min` and `max` values. The Servo implementation pulses a digital signal for a number of microseconds that is proportional to the angle of rotation. Scripts may provide the number of microseconds for the signal pulse instead of degrees, for greater precision. @@ -619,9 +619,9 @@ import RMT from "pins/rmt"; ### `constructor(dictionary)` -The RMT constructor initializes the RMT module and associates it with the specified pin. +The RMT constructor initializes the RMT module and associates it with the specified pin. -The RMT constructor takes a dictionary. The `pin` property is required, and specifies the pin to associate with the RMT module. +The RMT constructor takes a dictionary. The `pin` property is required, and specifies the pin to associate with the RMT module. ```js let rmt = new RMT({pin: 17}); @@ -629,7 +629,7 @@ let rmt = new RMT({pin: 17}); The constructor dictionary also has several optional properties: -- The `channel` property specifies the RMT channel to use with this instance, with a default value of `0`. +- The `channel` property specifies the RMT channel to use with this instance, with a default value of `0`. - The `divider` property specifies the clock divider used to generate RMT ticks, with a range of `1` to `255` and a default value of `255`. - The `direction` property specifies whether to use this RMT as an input or an output. Use `"rx"` for input and `"tx"` for output. The default is output. @@ -665,7 +665,7 @@ The write is performed asynchronously, so `write` returns immediately. When the ### `onWriteable()` callback -A script may install an `onWriteable` callback on the instance to be invoked when the RMT module is ready to write data. +A script may install an `onWriteable` callback on the instance to be invoked when the RMT module is ready to write data. ```js rmt.onWritable = function() { @@ -679,12 +679,12 @@ The `onWriteable` function is called once when the RMT module is initialized and ### `read(buffer)` -The `read` function returns RMT data in an ArrayBuffer provided by the `buffer` argument. Up to `buffer.byteLength` bytes from the RMT module's ring buffer are returned in the ArrayBuffer. +The `read` function returns RMT data in an ArrayBuffer provided by the `buffer` argument. Up to `buffer.byteLength` bytes from the RMT module's ring buffer are returned in the ArrayBuffer. -`read` returns an object with three properties: +`read` returns an object with three properties: -- The `buffer` property is the ArrayBuffer provided to `read` as an argument, filled with the received pulse duration sequence read by the RMT module. -- The `count` property is the total number of pulses received in the sequence. +- The `buffer` property is the ArrayBuffer provided to `read` as an argument, filled with the received pulse duration sequence read by the RMT module. +- The `count` property is the total number of pulses received in the sequence. - The `phase` property is the logic level of the first item in the sequence (`0` or `1`) — subsequent pulses in the `buffer` alternate logic levels. ```js diff --git a/documentation/piu/ae motion export.md b/documentation/piu/ae motion export.md index 87bbfcd879..ba5a236a25 100644 --- a/documentation/piu/ae motion export.md +++ b/documentation/piu/ae motion export.md @@ -6,7 +6,7 @@ Revised: September 26, 2017 Adobe After Effects can be used to export motion data into a Moddable sample app for use in development. -Moddable motion control only supports position. +Moddable motion control only supports position. In AE only layers with assets are exported and only positions are exported. Scaling, rotation, transparncy, etc. are not exported. @@ -16,16 +16,16 @@ Piu interpolates linearly between values in the array. You can reduce the frame Install the ae2piu.jsx script in the "scripts" folder within your After Effects application folder. - + + - ### Exporting motion data To run the script select "ae2piu.jsx" from the File -> Scripts menu. - + When you run the export script in After Effects, it displays a dialog box to select a folder. Create a new folder the first time. The export script copies the assets and creates the manifest.json and main.js files for a complete Moddable application. To build the project and run in the Moddable Simulator use the following command. @@ -41,10 +41,10 @@ Time values are exported as milliseconds. AE easing is not exported but Moddable easing can be added to the exported code. -Example: (null replaced by Math.quadEaseOut) +Example: (null replaced by Math.quadEaseOut) this.steps(ball, { x:ballX, y:ballY }, 2333, null, 0, 0); - + this.steps(ball, { x:ballX, y:ballY }, 2333, Math.quadEaseOut, 0, 0); diff --git a/documentation/piu/die-cut.md b/documentation/piu/die-cut.md index 4f6303c3f1..f0b6f4a409 100644 --- a/documentation/piu/die-cut.md +++ b/documentation/piu/die-cut.md @@ -7,7 +7,7 @@ Revised: November 22, 2016 To get animations on a screen connected to a microcontroller by a serial interface (SPI), the game is to minimize the number of pixels that change from frame to frame. > FYI, here is what is happening at every frame when changes in the appearance or the layout invalidate and update the screen: -> +> > - The dirty region accumulates the invalidations. > - The containment hierarchy is traversed once to build the command list that will update the screen. > - The dirty region and the command list are decomposed into rectangles and display lists. @@ -43,14 +43,14 @@ Let us begin with a static example: }), ] })); - + The `empty`, `or`, `xor` and `sub` methods are chainable operations to build the region. The `cut` method changes the region. If you add the `TestContainer` to an application, here is what it will look like: ![](./../assets/die-cut/die-cut.png) -But of course the `die` object is mostly interesting to build animations and transitions. You will find examples in the Piu libraries: WipeTransition and CombTransition. +But of course the `die` object is mostly interesting to build animations and transitions. You will find examples in the Piu libraries: WipeTransition and CombTransition. Let us build a "venitian blind" transition: @@ -88,9 +88,9 @@ The `attach` and `detach` methods allow to temporarily insert a `die` object in ## Reference -The `die` object is a `layout` object that allows to “die cut” its contents with a region. The `die` object maintains two regions: +The `die` object is a `layout` object that allows to “die cut” its contents with a region. The `die` object maintains two regions: -- the work region that the available operations build, +- the work region that the available operations build, - the clip region that clips the contents of the `die` object Both regions are initially empty. @@ -102,13 +102,13 @@ Prototype inherits from `Layout.prototype`. ##### `Die.prototype.and(x, y, width, height)` > `x, y, width, height` a local rectangle, in pixels -> +> > Intersect the rectangle with the work region. Return this. ##### `Die.prototype.attach(content)` > `content ` the `content` object to attach -> +> > Bind the `die` object to the content hierarchy by replacing the specified `content` object in the content's container with this `die` object and adding the `content` object to this `die` object. ##### `Die.prototype.cut()` @@ -130,25 +130,25 @@ Prototype inherits from `Layout.prototype`. ##### `Die.prototype.or(x, y, width, height)` > `x, y, width, height` a local rectangle, in pixels -> +> > Inclusively union the rectangle with the work region. Return `this`. ##### `Die.prototype.set(x, y, width, height)` > `x, y, width, height` a local rectangle, in pixels -> +> > Set the work region to the rectangle. Return `this`. ##### `Die.prototype.sub(x, y, width, height)` > `x, y, width, height` a local rectangle, in pixels -> +> > Subtract the rectangle from the work region. Return `this`. ##### `Die.prototype.xor(x, y, width, height)` > `x, y, width, height` a local rectangle, in pixels -> +> > Exclusively union the work region with the rectangle. Return `this`. diff --git a/documentation/piu/expanding-keyboard.md b/documentation/piu/expanding-keyboard.md index d3a435b408..d4be71f9f3 100644 --- a/documentation/piu/expanding-keyboard.md +++ b/documentation/piu/expanding-keyboard.md @@ -2,7 +2,7 @@ Copyright 2019 Moddable Tech, Inc.
Revised: July 2, 2019 -The vertical and horizontal expanding keyboard modules implement touch screen keyboards for use with [Piu](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/piu/piu.md) on Moddable One and Moddable Two [products](https://www.moddable.com/product.php). The keys automatically expand when tapped, eliminating the need for a stylus. Both keyboards implement the same API. +The vertical and horizontal expanding keyboard modules implement touch screen keyboards for use with [Piu](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/piu/piu.md) on Moddable One and Moddable Two [products](https://www.moddable.com/product.php). The keys automatically expand when tapped, eliminating the need for a stylus. Both keyboards implement the same API. - **Source code:** [`vertical/keyboard.js`](../../modules/input/expanding-keyboard/vertical/keyboard.js) [`horizontal/keyboard.js`](../../modules/input/expanding-keyboard/horizontal/keyboard.js) - **Relevant Examples:** [vertical-expanding-keyboard](../../examples/piu/vertical-expanding-keyboard/main.js) [horizontal-expanding-keyboard](../../examples/piu/horizontal-expanding-keyboard/main.js) @@ -43,7 +43,7 @@ import {KeyboardField} from "common/keyboard"; #### `HorizontalExpandingKeyboard(behaviorData, dictionary)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `behaviorData` | `*` | A parameter that is passed into the `onCreate `function of the keyboard's `behavior`. This may be any type of object, including `null` or a dictionary with arbitrary parameters. | `dictionary` | `object` | An object with properties to configure the resulting keyboard. Only parameters specified in the [Dictionary](#keyboard-dictionary) section below will have an effect; other parameters will be ignored. @@ -60,7 +60,7 @@ let keyboard = new VerticalExpandingKeyboard(null, { Style:KeyboardStyle, target ### Dictionary | Parameter | Type | Default Value | Description | -| :---: | :---: | :---: | :--- | +| :---: | :---: | :---: | :--- | | `Style` | `style` | n/a | **Required.** A Piu Style object that will be used for the text on keys. | | `target` | `object` | n/a | **Required.** A Piu Container object that will receive the `onKeyUp` event. | | `doTransition` | `boolean` | `false`| Whether or not to transition in the keyboard when it is first displayed and transition out when dismissed. | @@ -71,7 +71,7 @@ let keyboard = new VerticalExpandingKeyboard(null, { Style:KeyboardStyle, target #### `onKeyboardOK(container, text)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | | `text` | `string` | The complete string entered into the field | @@ -80,7 +80,7 @@ The keyboard bubbles this event when the OK button is pressed. #### `onKeyboardRowsContracted(container)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | The keyboard bubbles this event when it is done horizontally contracting the keyboard rows back to the unzoomed view. @@ -88,7 +88,7 @@ The keyboard bubbles this event when it is done horizontally contracting the key #### `onKeyboardRowsExpanded(container)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | The keyboard bubbles this event when it is done horizontally expanding the keyboard rows to the zoomed view. @@ -96,7 +96,7 @@ The keyboard bubbles this event when it is done horizontally expanding the keybo #### `onKeyboardTransitionFinished(container, out)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | | `out` | `boolean` | Set `true` when the keyboard transitions out of view, `false` when the keyboard transitions into view | @@ -105,7 +105,7 @@ The keyboard bubbles this event when it is done transitioning on and off the scr #### `onKeyUp(container, key)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | | `key` | `string` | The string value of the key that was pressed (e.g., `'a'`, `'3'`, `'$'`). It can also be `\b` for backspace or `\r` for the submit button.| @@ -120,7 +120,7 @@ The keyboard bubbles the `onKeyUp` event when a key is released. The `onKeyUp` f #### `KeyboardField(behaviorData, dictionary)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `behaviorData` | `*` | A parameter that is passed into the `onCreate `function of the keyboard field's `behavior`. This may be any type of object, including `null` or a dictionary with arbitrary parameters. | `dictionary` | `object` | An object with properties to configure the resulting keyboard field. Only parameters specified in the [Dictionary](#keyboard-field-dictionary) section below will have an effect; other parameters will be ignored. @@ -135,7 +135,7 @@ let keyboardField = new KeyboardField(null, { Style:FieldStyle }); ### Dictionary | Parameter | Type | Default Value | Description | -| :---: | :---: | :---: | :--- | +| :---: | :---: | :---: | :--- | | `Style` | `style` | n/a | **Required.** A Piu Style object that will be used for the keyboard entry text. | | `password` | `boolean` | `false` | Set `true` to enable password mode. The password mode hides each character displayed after a short delay. | @@ -144,7 +144,7 @@ let keyboardField = new KeyboardField(null, { Style:FieldStyle }); #### `onKeyboardOK(container, text)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `container` | `object` | The behavior's Container object | | `text` | `string` | The complete string entered into the field | diff --git a/documentation/piu/keyboard.md b/documentation/piu/keyboard.md index 87839ab2ba..bb27d2b3cf 100644 --- a/documentation/piu/keyboard.md +++ b/documentation/piu/keyboard.md @@ -30,7 +30,7 @@ import {Keyboard, BACKSPACE, SUBMIT} from "keyboard"; #### `Keyboard(behaviorData, dictionary)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `behaviorData` | `*` | A parameter that is passed into the `onCreate `function of the keyboard's `behavior`. This may be any type of object, including `null` or a dictionary with arbitrary parameters. | `dictionary` | `object` | An object with properties to configure the resulting keyboard. Only parameters specified in the [Dictionary](#keyboard-dictionary) section below will have an effect; other parameters will be ignored. @@ -47,7 +47,7 @@ let keyboard = new Keyboard(null, {style: OpenSans18, doTransition: false}) ### Dictionary | Parameter | Type | Default Value | Description | -| :---: | :---: | :---: | :--- | +| :---: | :---: | :---: | :--- | | `style` | `style` | n/a | **Required.** A Piu Style object that will be used for the text on keys. | | `bgColor` | `string` | `"#5b5b5b"`| The background fill color. | | `doTransition` | `boolean` | `false`| Whether or not to transition in the keyboard when it is first displayed. | @@ -71,7 +71,7 @@ The keyboard will bubble this event when it is done transitioning off-screen. Th #### `onKeyDown(key)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `key` | `string` | In most cases, the string will be the value of the key that is down (e.g. `"a"`, `"3"`, `"$"`). It can also be one of the two constants exported by the module: `BACKSPACE` or `SUBMIT` which indicate that those keys are down on the keyboard.| The keyboard will bubble this event when a key is pressed down. The `onKeyDown` function will usually be implemented and triggered in the calling application's behavior. @@ -82,7 +82,7 @@ The keyboard will bubble this event when a key is pressed down. The `onKeyDown` #### `onKeyUp(key)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `key` | `string` | In most cases, the string will be the value of the key that was released (e.g. `"a"`, `"3"`, `"$"`). It can also be one of the two constants exported by the module: `BACKSPACE` or `SUBMIT` which indicate that those keys were released on the keyboard.| The keyboard will bubble an event `onKeyUp` when a key is released. The `onKeyUp` function will usually be implemented and triggered in the calling application's behavior. @@ -94,7 +94,7 @@ The keyboard will bubble an event `onKeyUp` when a key is released. The `onKeyUp #### `doKeyboardTransitionOut(keyboard)` | Argument | Type | Description | -| :---: | :---: | :--- | +| :---: | :---: | :--- | | `keyboard` | `keyboard` | The `keyboard` object that received the event. | This function can be triggered to cause the keyboard to transition off screen. When the transition is complete, the `onKeyboardTransitionFinished` event will be bubbled by the keyboard. diff --git a/documentation/piu/localization.md b/documentation/piu/localization.md index 51ab3d44e4..15ad7bf241 100644 --- a/documentation/piu/localization.md +++ b/documentation/piu/localization.md @@ -10,7 +10,7 @@ When using JavaScript, the most obvious format to localize strings is a dictiona "I love you": "I love you", "Me neither": "Me neither", }; - + var fr = { "I love you": "Je t'aime", "Me neither": "Moi non plus", @@ -20,8 +20,8 @@ When using JavaScript, the most obvious format to localize strings is a dictiona function localize(it) { return language[it]; } - -It is not always possible to use the English string as the key, because of homonyms, contexts, etc. However, when it is possible, it is recommended: the code is easier to read and obvious redundancies are avoided. + +It is not always possible to use the English string as the key, because of homonyms, contexts, etc. However, when it is possible, it is recommended: the code is easier to read and obvious redundancies are avoided. The trivial examples here above are used to compare solutions here under. Of course real applications use dictionaries with thousands of entries, small and large keys and values, so multiply accordingly. @@ -32,11 +32,11 @@ Since usually applications need only one language at a time, dictionaries can be #### en.json {"I love you":"I love you","Me neither":"Me neither"} - + #### fr.json {"I love you":"Je t'aime","Me neither":"Moi non plus"} - + Storing JSON files in ROM is a waste since all dictionaries have to define all keys. For instance here above the keys `I love you` and `Me neither` are repeated in the English and French dictionaries. ROM|Size @@ -60,7 +60,7 @@ Instead of JSON files, dictionaries could be JavaScript modules that XS can comp #### en.js export default {"I love you":"I love you","Me neither":"Me neither"} - + #### fr.js export default {"I love you":"Je t'aime","Me neither":"Moi non plus"} @@ -77,12 +77,12 @@ Moreover, since XS has no special case for such objects, the time to lookup a st ## Strings Tables -The first optimization is to use strings tables instead of JSON files or JavaScript modules. Each table begins with the length of the table followed by the offsets of the strings in the table. All numbers are little-endian 32-bit integers. +The first optimization is to use strings tables instead of JSON files or JavaScript modules. Each table begins with the length of the table followed by the offsets of the strings in the table. All numbers are little-endian 32-bit integers. #### locals.en.mhr 2 12 23 I love you Me neither - + #### locals.fr.mhr 2 12 22 Je t'aime Moi non plus @@ -98,7 +98,7 @@ A tool can generate the strings table from the JSON files. Applications can get ## Strings Indexes -Now something is of course necessary to map keys to indexes into the tables, so `I love you` maps to `0`, `Me neither ` maps to `1`, etc. +Now something is of course necessary to map keys to indexes into the tables, so `I love you` maps to `0`, `Me neither ` maps to `1`, etc. Again a dictionary could be used, at least there would be only one dictionary for all languages. @@ -112,20 +112,20 @@ Again a dictionary could be used, at least there would be only one dictionary fo function localize(it) { return language.get(locals[it]); } - + But such a dictionary would have the already mentioned drawbacks: populating the XS symbols table and taking time to lookup an index. ## Minimal Perfect Hashing When all keys and results are known, a perfect hash function can map keys into results without collisions. A practical solution is to use two hash functions and an intermediary table. The first hash function maps keys into seeds. The second hash function uses the seeds to maps keys into results. The seeds table can be sparse, but both the seeds and results tables contain only one entry by result. Finding the seeds take some time but is done by a tool at build time. -Here are some references: +Here are some references: - [CMPH](http://cmph.sourceforge.net/index.html): a C library with a lot of algorithms and explanations. - [Steve Hanov's blog](http://stevehanov.ca/blog/index.php?id=119): a detailed presentation of the practical solution in PHP. - [mixu/perfect](https://github.com/mixu/perfect): a node.js port. -Here the results are indexes into the strings tables. So the results table does not need to be stored, the results table is only used to reorder the strings tables. +Here the results are indexes into the strings tables. So the results table does not need to be stored, the results table is only used to reorder the strings tables. Only the seeds table needs to be stored. Negative seeds signal that the second hash function can be skipped, the index is the absolute of the seed minus one. @@ -152,12 +152,12 @@ locals.mhi (debug)|46 bytes ## mclocal -**mclocal** is a command line tool that generates strings tables and seeds table from JSON files. +**mclocal** is a command line tool that generates strings tables and seeds table from JSON files. For instance mclocal en.json fr.json - + will generate the `locals.en.mhr`, `locals.fr.mhr` and `locals.mhi` here above. **mclocal** unions the keys from all the JSON files and reports missing keys in the JSON files. @@ -179,22 +179,22 @@ By convention, **mcconfig** will generate a make file with a rule to call **mclo Piu defines a class, `Locals`, to get localized strings and to switch languages. var locals = new Locals; - + The constructor takes two arguments, `name` and `language`. The defaults are `locals` and `en`. Resources are accessed by combining `name`, `language` and the `.mhi` or `.mhr` extensions. - + Applications switch the language with an accessor. - + var what = locals.get("I love you"); // what == "I love you" locals.language = "fr"; var quoi = locals.get("I love you"); // quoi == "Je t'aime" - + For convenience, applications can define a global function to localize strings. global.localize = function(it) { return locals.get(it); - } - - + } + + diff --git a/documentation/piu/piu.md b/documentation/piu/piu.md index 8a7f54491f..0fe1f37254 100644 --- a/documentation/piu/piu.md +++ b/documentation/piu/piu.md @@ -47,7 +47,7 @@ Piu is a user interface framework designed to run on microcontrollers. The progr ## Inheritance Hierarchy -Figure 1 summarizes the inheritance hierarchy for the objects described in this document. +Figure 1 summarizes the inheritance hierarchy for the objects described in this document. **Figure 1.** Piu Inheritance Hierarchy @@ -58,7 +58,7 @@ The basic relationship between these objects in the context of a Piu application - Graphical parts of the user interface are all `content` objects - `skin`, `style`, and `texture` objects customize the look (colors, fonts, etc.) of `content` objects - `behavior` objects are bound to `content` objects to handle events -- `timeline` and `transition` objects animate `content` objects +- `timeline` and `transition` objects animate `content` objects ## Introduction to Important Concepts @@ -77,7 +77,7 @@ Applications use constructors to define `content` and `container` objects. These #### Bound and Unbound Contents -Contents that are not attached to the containment hierarchy are called *unbound* contents; contents attached to the containment hierarchy, *bound* contents. Only objects that are part of the containment hierarchy appear on screen. +Contents that are not attached to the containment hierarchy are called *unbound* contents; contents attached to the containment hierarchy, *bound* contents. Only objects that are part of the containment hierarchy appear on screen. Unbound contents do not participate in layout. They are neither measured nor fitted; consequently, their position and size are `undefined` and cannot be changed. @@ -90,7 +90,7 @@ let after = content.position; // {x: 160, y:120} (assuming the application is 32 #### Constraints -The coordinates of an object define implicit constraints on its position and size. +The coordinates of an object define implicit constraints on its position and size. For example, centered content and contents whose sizes/position are dependent on their container's size/position cannot move. @@ -99,12 +99,12 @@ For example, centered content and contents whose sizes/position are dependent on let centeredContent = new Content(null, { width: 10, height: 10 }); -let dependentOnContainerContent = new Content(null, { +let dependentOnContainerContent = new Content(null, { top: 0, left: 0, bottom: 100, right: 100, }); // Can move -let unconstrainedContent = new Content(null, { +let unconstrainedContent = new Content(null, { top: 0, left: 0, height: 100, width: 100 }); ``` @@ -117,27 +117,27 @@ let unconstrainedContent = new Content(null, { All contents have a *measured width* and *measured height*, which are the default width and height computed by the content itself. For example, the measured width of the following content object will be 100. ```javascript -let sampleContent = new Content(null, { - width: 100 +let sampleContent = new Content(null, { + width: 100 }); ``` The measured width of the following content will be 0, because the content has no default width. ```javascript -let sampleContent = new Content(null, { - left: 0, right: 0 +let sampleContent = new Content(null, { + left: 0, right: 0 }); ``` The `coordinates` property of a `content` object reflect the content's measured size. This property can be changed at any time. ```javascript -sampleContent.coordinates = { +sampleContent.coordinates = { left: 0, width: 100, top: 0, - height: 100 + height: 100 }; ``` @@ -149,8 +149,8 @@ All contents also have a *fitted width* and *fitted height*, which are the effec If both `left` and `right` coordinates are defined, the content stretches horizontally with its container, and the fitted width of the content depends on the fitted width of its container. Similarly, if both `top` and `bottom` coordinates are defined, the content stretches vertically with its container, and the fitted height of the content depends on the fitted height of its container. For example, the fitted width and fitted height of the `sampleContent` object here will both be 100. ```javascript -let sampleContent = new Content(null, { - left: 0, right: 0 +let sampleContent = new Content(null, { + left: 0, right: 0 }); let sampleContainer = new Container(null, { height: 100, width: 100, @@ -163,8 +163,8 @@ let sampleContainer = new Container(null, { If a `left` or `right` coordinate (but not both) is defined, or if neither `left` nor `right` is defined, the fitted width equals the measured width. Similarly, if a `top` or `bottom` coordinate (but not both) is defined, or if neither `top` nor `bottom` is defined, the fitted width equals the measured height. For example, the fitted width and fitted height of the `sampleContent` object here will both be 50. ```javascript -let sampleContent = new Content(null, { - left: 0, top: 0, width: 50, height: 50 +let sampleContent = new Content(null, { + left: 0, top: 0, width: 50, height: 50 }); let sampleContainer = new Container(null, { height: 100, width: 100, @@ -331,7 +331,7 @@ Traces the specified string in the virtual machine of the hosted application. > Note: Strings will not be traced until a line break ("\n") has also been traced. ```javascript -trace("Hello world\n"); +trace("Hello world\n"); let sampleVariable = 2; trace(`sampleVariable value is: ${sampleVariable}\n`); // "sampleVariable value is 2" @@ -391,7 +391,7 @@ application.add(new SampleContainer({ title: "Tap to update", color: "blue" })); A `color` parameter can be passed into the dictionaries of `skin` and `style` constructors. To specify a color, you can use CSS names (Level 2) or hexadecimal notations (`"#RGB"`, `"#RGBA"`, `"#RRGGBB"`, `"#RRGGBBAA"`): - + ```javascript const whiteSkin = new Skin({ fill:"white" }); const redSkin = new Skin({ fill:"#F00" }); @@ -421,7 +421,7 @@ In dictionaries, colors can be a single color or an array of 2, 3, or 4 colors. ### Coordinates -All `content` objects have a `coordinates` property. The coordinates property is an object with `left`, `width`, `right`, `top`, `height`, and `bottom` properties, all of which can be `undefined`. The coordinates of contents determine their position and size relative to their container and their `previous` and `next` properties (other `content` objects in the same container). +All `content` objects have a `coordinates` property. The coordinates property is an object with `left`, `width`, `right`, `top`, `height`, and `bottom` properties, all of which can be `undefined`. The coordinates of contents determine their position and size relative to their container and their `previous` and `next` properties (other `content` objects in the same container). When a content's container is an `application`, `container`, `scroller`, or `layout` object: @@ -447,8 +447,8 @@ When a content's container is a `row` object: Every content in the containment hierarchy can be used as a clock to control time-based animation behaviors using its `duration`, `fraction`, `interval`, and `time` properties. -- The `duration` property is the duration of the animation, expressed in milliseconds. -- The `time` property provides the current time of the content’s clock. +- The `duration` property is the duration of the animation, expressed in milliseconds. +- The `time` property provides the current time of the content’s clock. - The `fraction` property is the ratio of the clock’s current time to the content’s duration. - The `interval` property is the time between frames (frame rate) of the animation, expressed in milliseconds. @@ -549,7 +549,7 @@ let expandingButton = new Content(null, { A `font` parameter must be passed into the dictionary of `style` constructors. -Piu uses bitmap fonts. The metrics are provided by binary FNT files, the glyphs are provided by PNG files. +Piu uses bitmap fonts. The metrics are provided by binary FNT files, the glyphs are provided by PNG files. Fonts are assets and must be defined in the resources of your manifest. Use the default target or the `-alpha` or `-color` pseudo targets for fonts. @@ -576,7 +576,7 @@ In order to cascade styles, you may want to use something similar to the [CSS fo const style = new Style({ font:"italic bold 16px Open Sans" }); ``` -In Piu, the font property has five optional parts, in that order: +In Piu, the font property has five optional parts, in that order: 1. style: `italic` | `normal` | `inherit` 2. weight: `100` | `ultralight` | `200` | `thin` | `300` | `light` | `400` | `normal` | `500` | `medium` | `600` | `semibold` | `700` | `bold` | `800` | `heavy` | `900` | `black` | `lighter` | `bolder` | `inherit ` @@ -600,7 +600,7 @@ For Piu to find the corresponding bitmap font files in your assets, you have to * the family, without spaces, * `-`, * the capitalized name of the stretch, if not `normal`, -* the capitalized name of the computed weight, if not `normal`, +* the capitalized name of the computed weight, if not `normal`, * the capitalized name of the style, if not `normal`, * `Regular`, if the stretch, the computed weight and the style are all `normal`, * `-`, @@ -624,20 +624,20 @@ Tiling skins allows content objects of different sizes to share a single asset. ```javascript let roundedRectangleTexture = new Texture("roundedRectangle.png"); -let roundedRectangleSkin = new Skin({ - texture: roundedRectangleTexture, - x: 0, y: 0, width: 30, height: 30, +let roundedRectangleSkin = new Skin({ + texture: roundedRectangleTexture, + x: 0, y: 0, width: 30, height: 30, tiles: { left: 5, right: 5, top: 5, bottom: 5 } }); let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" }); let smallText = new Label(null, { - skin: roundedRectangleSkin, top: 20, left: 20, height: 30, width: 30, + skin: roundedRectangleSkin, top: 20, left: 20, height: 30, width: 30, style: sampleStyle, string: "Hi" }); let bigText = new Text(null, { - skin: roundedRectangleSkin, top: 70, left: 20, height: 120, width: 100, + skin: roundedRectangleSkin, top: 70, left: 20, height: 120, width: 100, style: sampleStyle, string: "This is a long string" }); @@ -657,17 +657,17 @@ A common way that the `state` property is used is to update the color of content ```javascript let multiColoredSkin = new Skin({ fill: ["black", "white", "red"] }); -let blackContent = new Content(null, { - top: 20, left: 20, width: 80, height: 80, - skin: multiColoredSkin, state: 0, +let blackContent = new Content(null, { + top: 20, left: 20, width: 80, height: 80, + skin: multiColoredSkin, state: 0, }); -let redContent = new Content(null, { - top: 20, left: 120, width: 80, height: 80, +let redContent = new Content(null, { + top: 20, left: 120, width: 80, height: 80, skin: multiColoredSkin, state: 2 }); -let grayContent = new Content(null, { - top: 20, left: 220, width: 80, height: 80, - skin: multiColoredSkin, state: 0.5 +let grayContent = new Content(null, { + top: 20, left: 220, width: 80, height: 80, + skin: multiColoredSkin, state: 0.5 }); application.add(blackContent); application.add(redContent); @@ -678,7 +678,7 @@ application.add(grayContent); #### Reusing textures -It is often convenient to store several icons or other user interface elements in a single image. Specifying `states` and `variants` properties in the dictionary of `skin` constructors enables you to reference different sections of the same texture. This prevents an application from having to reference similar images and create multiple skins. +It is often convenient to store several icons or other user interface elements in a single image. Specifying `states` and `variants` properties in the dictionary of `skin` constructors enables you to reference different sections of the same texture. This prevents an application from having to reference similar images and create multiple skins. The `states` and `variants` properties of a skin are numerical values used to define the size of a single element in the texture. The `states` property represents the vertical offset between states, and the `variants` property represents the horizontal offset between variants. Here is an example of an asset that includes ten 28x28 pixel icons in one image, and a `skin` that will allow applications to reference each icon separately. @@ -686,9 +686,9 @@ The `states` and `variants` properties of a skin are numerical values used to de ```javascript const wiFiStripTexture = new Texture({ path:"wifi-strip.png" }); -const wiFiSkin = new Skin({ - texture: wiFiStripTexture, - width: 28, height: 28, +const wiFiSkin = new Skin({ + texture: wiFiStripTexture, + width: 28, height: 28, states: 28, variants: 28 }); ``` @@ -745,7 +745,7 @@ For the complete JavaScript programming interface, see [`piuAll.js`][0]. - **Source code:** [`piuApplication.c`][2] - **Relevant Examples:** all -All Piu applications must have an `application` object at the root of their containment hierarchy. All other `content` objects must be added to the `application` to appear on screen. +All Piu applications must have an `application` object at the root of their containment hierarchy. All other `content` objects must be added to the `application` to appear on screen. There is no default object, so you have to create one yourself and export it in the main module. @@ -753,7 +753,7 @@ There is no default object, so you have to create one yourself and export it in export default new Application(); ``` -Alternatively, you can export a function that returns an `application` object. +Alternatively, you can export a function that returns an `application` object. ```javascript export default function() { @@ -842,7 +842,7 @@ class SampleBehavior extends Behavior { } } -let sampleContent = new Content({ name: "Moddable" }, { +let sampleContent = new Content({ name: "Moddable" }, { active: true, height: 100, width: 100, skin: new Skin({fill: "blue"}), Behavior: SampleBehavior @@ -952,7 +952,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({fill: "white"}), contents: [ @@ -980,7 +980,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); -let SampleContainer = Container.template($ => ({ +let SampleContainer = Container.template($ => ({ top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: $.backgroundColor }), contents: [ @@ -1003,7 +1003,7 @@ Same as for `content` object (see [Dictionary](#content-dictionary) in the secti #### Prototype Description -Prototype inherits from `Content.prototype`. +Prototype inherits from `Content.prototype`. ##### Properties @@ -1034,7 +1034,7 @@ let ColoredSquare = Content.template($ => ({ height: 100, width: 100, skin: new Skin({ fill: $ }) })); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), }); @@ -1086,7 +1086,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1120,7 +1120,7 @@ class SampleBehavior extends Behavior { } } -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1154,7 +1154,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1188,7 +1188,7 @@ class SampleBehavior extends Behavior { } } -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1210,7 +1210,7 @@ application.add(sampleContainer); **`remove(content)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `content` | `content` | The `content` object to remove. Its container must be this container. Removes the specified `content` object from this container @@ -1224,7 +1224,7 @@ let ColoredSquare = Content.template($ => ({ let redSquare = new ColoredSquare("red"); let blueSquare = new ColoredSquare("blue"); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1258,7 +1258,7 @@ let ColoredSquare = Content.template($ => ({ let redSquare = new ColoredSquare("red"); let blueSquare = new ColoredSquare("blue"); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1296,11 +1296,11 @@ class SwitchScreenBehavior extends Behavior { } } let ColoredScreen = Container.template($ => ({ - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: $.color }), contents: [ Content($, { - active: true, height: 100, width: 100, + active: true, height: 100, width: 100, skin: new Skin({ fill: $.nextColor }), Behavior: SwitchScreenBehavior }) @@ -1327,7 +1327,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); -let sampleContainer = new Container(null, { +let sampleContainer = new Container(null, { active: true, top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), contents: [ @@ -1365,7 +1365,7 @@ This event is triggered when a `transition` object starts in the specified `cont **`onTransitionEnded(container)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `container` | `container` | The `container` object that triggered the event This event is triggered when a `transition` object ends in the specified `container` object. @@ -1384,14 +1384,14 @@ Applications use `content` objects for graphical parts of their user interface, ##### `Content([behaviorData, dictionary])` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `behaviorData` | `*` | A parameter that is passed into the `onCreate` function of this content's `behavior`. This may be any type of object, including `null` or a dictionary with arbitrary parameters. | `dictionary` | `object` | An object with properties to initialize the result. Only parameters specified in the [Dictionary](#content-dictionary) section below will have an effect; other parameters will be ignored. Returns a `content` instance, an object that inherits from `Content.prototype` ```javascript -let sampleContent = new Content("Hello", { +let sampleContent = new Content("Hello", { top: 0, right: 50, height: 100, width: 100, skin: new Skin({fill: "blue"}), Behavior: class extends Behavior { @@ -1404,7 +1404,7 @@ application.add(sampleContent); ``` ![](../assets/piu/sampleContent1.png) - + ##### `Content.template(anonymous)` | Arguments | Type | Description @@ -1414,7 +1414,7 @@ application.add(sampleContent); Returns a constructor, a function that creates instances of `Content.prototype`. The `prototype` property of the result is `Content.prototype`. The result also provides a `template` function. ```javascript -let SampleContent = Content.template($ => ({ +let SampleContent = Content.template($ => ({ height: 100, width: 100, skin: new Skin({fill: $.color}), Behavior: class extends Behavior { @@ -1437,7 +1437,7 @@ application.add(new SampleContent({color: "blue"})); | `active` | `boolean` | If `true`, this content can be touched; that is, it triggers touch events. | | `anchor` | `string` | Creates an anchor, a reference to the created `content` object in the instantiating data | `backgroundTouch ` | `boolean` | If `true`, this container receives any touch events that are received by its contents; that is, it will trigger touch events when one of its contents has been touched. -| `Behavior` | `function` | A function that creates instances of `Behavior.prototype`; generally a class that extends the `Behavior` class. This content will create an instance of this `behavior`, set its `behavior` parameter to the created instance, and trigger the `onCreate` method. +| `Behavior` | `function` | A function that creates instances of `Behavior.prototype`; generally a class that extends the `Behavior` class. This content will create an instance of this `behavior`, set its `behavior` parameter to the created instance, and trigger the `onCreate` method. | `bottom` | `number` | This content's `bottom` coordinate, in pixels (setting `bottom` in the created instance's `coordinates` property) | `duration` | `number` |This content's duration, in milliseconds. This content triggers the `onFinished` event when its clock is running and its time equals its duration. | `exclusiveTouch` | `boolean` | If `true`, this content always captures touches; that is, `captureTouch` is implicitly invoked on `onTouchDown` for this content. Setting `exclusiveTouch` to `true` is equivalent to calling `captureTouch` in response to the `onTouchDown` event for every touch id. @@ -1462,7 +1462,7 @@ application.add(new SampleContent({color: "blue"})); #### Prototype Description -Prototype inherits from `Object.prototype`. +Prototype inherits from `Object.prototype`. ##### Properties @@ -1491,14 +1491,14 @@ Prototype inherits from `Object.prototype`. | `previous` | `object` | | ✓ | The previous `content` object in this content's container; `null` if this content is the first `content` object of this content's container or if this content has no container | `running` | `boolean` | | ✓ | If `true`, this content's clock is running. | `size` | `object` | | | This content's size, as an object with `width` and `height` number properties, specified in pixels -| `skin` | `skin` | `null` | | This content's skin or `null` +| `skin` | `skin` | `null` | | This content's skin or `null` `state` | `number` | 0 | | This content's state. If this content's skin defines states, setting the state changes the appearance of this content. | `style` | `style` | `null` | |This content's style or `null` | `time` | `number` | 0 | |This content's time, in milliseconds. When its time is set, this content triggers the `onTimeChanged` event. | `variant` | `number` | 0 | |This content's variant. If this content's skin defines variants, setting the variant changes the appearance of this content. | `visible` | `boolean` | `true` | |If `true`, this content is visible. | `width` | `number` | | |This content's width, in pixels -| `x` | `number` | | | This content's global x position. If this content is unbound, the getters return `undefined` and the setters are ignored. +| `x` | `number` | | | This content's global x position. If this content is unbound, the getters return `undefined` and the setters are ignored. | `y` | `number` | | |This content's global y position. If this content is unbound, the getters return `undefined` and the setters are ignored. @@ -1507,7 +1507,7 @@ Prototype inherits from `Object.prototype`. **`bubble(id [, ...])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `id` | `string` | The name of the event to trigger | `...` | `*` | Zero or more extra parameters @@ -1542,7 +1542,7 @@ application.add(outerContainer); **`captureTouch(id, x, y, ticks)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `id` | `number` | The identifier of the touch | `x, y` | `number` | The global position of the touch, in pixels | `ticks` | `number` | The global time of the touch @@ -1559,7 +1559,7 @@ class BlueBehavior extends Behavior { trace("Blue touch ended\n"); } } -let blueCapturingContent = new Content(null, { +let blueCapturingContent = new Content(null, { active: true, top: 25, left: 25, height: 50, width: 50, skin: new Skin({fill: "blue"}), Behavior: BlueBehavior @@ -1576,7 +1576,7 @@ class RedBehavior extends Behavior { trace("Red touch ended\n"); } } -let redContainer = new Container(null, { +let redContainer = new Container(null, { active: true, backgroundTouch: true, top: 0, left: 0, height: 100, width: 100, skin: new Skin({fill: "red"}), @@ -1693,8 +1693,8 @@ Returns this content if this content is active, bound, and contains the position > Note that this function should only be used after a content has been measured and fitted; otherwise it will always return `undefined`. ```javascript -let sampleContent = new Content(null, { - active: true, top: 0, left: 0, height: 100, width: 100, +let sampleContent = new Content(null, { + active: true, top: 0, left: 0, height: 100, width: 100, skin: new Skin({fill: "blue"}), Behavior: class extends Behavior { onDisplaying(content) { @@ -1706,7 +1706,7 @@ let sampleContent = new Content(null, { ``` *** - + **`measure()`** Returns the [measured size](#measured-size) of this content, as an object with `width` and `height` parameters. @@ -1714,8 +1714,8 @@ Returns the [measured size](#measured-size) of this content, as an object with ` Example 1: ```javascript -let sampleContent = new Content(null, { - top: 0, left: 0, height: 100, width: 100, +let sampleContent = new Content(null, { + top: 0, left: 0, height: 100, width: 100, skin: new Skin({fill: "blue"}) }); application.add(sampleContent); @@ -1728,7 +1728,7 @@ let fittedWidth = sampleContent.width; // 100 Example 2: ```javascript -let sampleContent = new Content(null, { +let sampleContent = new Content(null, { top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({fill: "blue"}) }); @@ -1740,24 +1740,24 @@ let fittedWidth = sampleContent.width; // 240 (assuming running on 240x320 scr ``` *** - + **`moveBy(x, y)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y` | `number` | The deltas by which to move this content, in pixels Moves this content as specified by the parameters. If the content's coordinates constrain its position, the `moveBy` function ignores the corresponding horizontal or vertical deltas. ```javascript -let unconstrainedContent = new Content(null, { +let unconstrainedContent = new Content(null, { top: 0, left: 0, height: 100, width: 100, skin: new Skin({fill: "blue"}), }); application.add(unconstrainedContent); unconstrainedContent.moveBy(100,100); // Moves unconstrainedContent 100 pixels in the x and y directions -let constrainedContent = new Content(null, { +let constrainedContent = new Content(null, { top: 0, left: 0, bottom: 140, right: 220, skin: new Skin({fill: "red"}), }); @@ -1778,14 +1778,14 @@ constrainedContent.moveBy(100,100); // Does nothing Sizes this content as specified by the parameters. If this content's coordinates constrain its size, the `sizeBy` function ignores the corresponding horizontal or vertical deltas. ```javascript -let unconstrainedContent = new Content(null, { +let unconstrainedContent = new Content(null, { top: 0, left: 0, height: 100, width: 100, skin: new Skin({fill: "blue"}), }) application.add(unconstrainedContent); -unconstrainedContent.sizeBy(100,100); // Makes unconstrainedContent 100 pixels wider and taller +unconstrainedContent.sizeBy(100,100); // Makes unconstrainedContent 100 pixels wider and taller -let constrainedContent = new Content(null, { +let constrainedContent = new Content(null, { top: 0, left: 0, bottom: 140, right: 220, skin: new Skin({fill: "red"}), }) @@ -1815,7 +1815,7 @@ class SampleBehavior extends Behavior { content.state = state; } } -let sampleContent = new Content(null, { +let sampleContent = new Content(null, { height: 100, width: 100, skin: new Skin({fill: ["red", "orange", "yellow", "green"]}), Behavior: SampleBehavior @@ -1849,7 +1849,7 @@ class SampleBehavior extends Behavior { content.start(); } } -let sampleContent = new Content(null, { +let sampleContent = new Content(null, { active: true, height: 100, width: 100, skin: new Skin({ fill: ["blue", "white"]}), Behavior: SampleBehavior @@ -1862,7 +1862,7 @@ application.add(sampleContent); #### Events -The following standard events are triggered by `content` objects. +The following standard events are triggered by `content` objects. **`onCreate(content, data, context)`** @@ -1908,10 +1908,10 @@ This event is triggered when the time of the specified `content` object changes. **`onTouchBegan(content, id, x, y, ticks)`** **`onTouchCancelled(content, id)`** - + **`onTouchEnded(content, id, x, y, ticks)`** - -**`onTouchMoved(content, id, x, y, ticks)`** + +**`onTouchMoved(content, id, x, y, ticks)`** | Argument | Type | Description | | --- | --- | :--- | @@ -1929,9 +1929,9 @@ These events are triggered when the specified `content` object is active and tou The `die` object is a `layout` object that allows you to “die cut” its contents with a region, minimizing the areas to invalidate and to update. These are useful for building animations and transitions on constrained devices that cannot update every screen pixel at every frame. -The `die` object maintains two regions: +The `die` object maintains two regions: -- the work region that the available operations build, +- the work region that the available operations build, - the clip region that clips the contents of the `die` object Both regions are initially empty. @@ -1957,15 +1957,15 @@ let sampleDie = new Die(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] }); let sampleScreenWithDie = new Container(null, { - left:0, right:0, top:0, bottom:0, + left:0, right:0, top:0, bottom:0, contents: [ Content(null, { top: 0, bottom: 120, left: 0, right: 0, @@ -2001,15 +2001,15 @@ let SampleDie = Die.template($ => ({ } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] })); let sampleScreenWithDie = new Container(null, { - left:0, right:0, top:0, bottom:0, + left:0, right:0, top:0, bottom:0, contents: [ Content(null, { top: 0, bottom: 0, left: 0, right: 0, @@ -2060,8 +2060,8 @@ let sampleContainer = new Container(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] @@ -2084,8 +2084,8 @@ application.add(sampleContainer); Binds the `die` object to the containment hierarchy by replacing the specified `content` object in the content's container with this `die` object and adding the `content` object to this `die` object. ```javascript -let whiteScreen = new Content(null, { - left:0, right:0, top:0, bottom:0, +let whiteScreen = new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), Behavior: class extends Behavior { onDisplaying(content) { @@ -2098,8 +2098,8 @@ let whiteScreen = new Content(null, { } } }); -let blueScreen = new Content(null, { - left:0, right:0, top:0, bottom:0, +let blueScreen = new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }), }); application.add(whiteScreen); @@ -2120,8 +2120,8 @@ Copies the work region into the current region, and invalidates only the differe Unbind this `die` object from the content hierarchy by removing the first `content` object from this `die` object and replacing this `die` object in its container with the removed `content` object. ``` -let whiteScreen = new Content(null, { - active: true, left:0, right:0, top:0, bottom:0, +let whiteScreen = new Content(null, { + active: true, left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), Behavior: class extends Behavior { onTouchBegan(content) { @@ -2139,8 +2139,8 @@ let whiteScreen = new Content(null, { } } }); -let blueScreen = new Content(null, { - active: true, left:0, right:0, top:0, bottom:0, +let blueScreen = new Content(null, { + active: true, left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "blue" }), }); application.add(whiteScreen); @@ -2184,8 +2184,8 @@ let sampleContainer = new Container(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] @@ -2202,7 +2202,7 @@ application.add(sampleContainer); **`set(x, y, width, height)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y, width, height` | `number` | A local rectangle, in pixels Sets the work region to the rectangle and returns `this`. @@ -2220,8 +2220,8 @@ let sampleContainer = new Container(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] @@ -2238,7 +2238,7 @@ application.add(sampleContainer); **`sub(x, y, width, height)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y, width, height` | `number` | A local rectangle, in pixels @@ -2260,8 +2260,8 @@ let sampleContainer = new Container(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] @@ -2278,7 +2278,7 @@ application.add(sampleContainer); **`xor(x, y, width, height)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y, width, height` | `number` | A local rectangle, in pixels Exclusively unions the work region with the rectangle and returns `this`. @@ -2297,8 +2297,8 @@ let sampleContainer = new Container(null, { } }, contents: [ - new Content(null, { - left:0, right:0, top:0, bottom:0, + new Content(null, { + left:0, right:0, top:0, bottom:0, skin: new Skin({ fill: "white" }), }), ] @@ -2313,7 +2313,7 @@ application.add(sampleContainer); ### Image Object - **Source code:** [`piuImage.c`][30] -- **Relevant Examples:** [images][31] +- **Relevant Examples:** [images][31] The `image` object is a `content` object that displays images. @@ -2417,7 +2417,7 @@ Prototype inherits from `Content.prototype`. - **Source code:** [`piuLabel.c`][8] - **Relevant Examples:** [cards][24], [keyboard][20] -The `label` object is a `content` object that renders a string on a single line with a single style. The string is truncated if it does not fit the bounds of the `label` object. +The `label` object is a `content` object that renders a string on a single line with a single style. The string is truncated if it does not fit the bounds of the `label` object. #### Constructor Description @@ -2433,7 +2433,7 @@ Returns a `label` instance, an object that inherits from `Label.prototype` ```javascript let sampleStyle = new Style({ font:"600 28px Open Sans", color: "blue" }); let sampleLabel = new Label(null, { - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), style: sampleStyle, string: "Hello, World!" }); @@ -2607,7 +2607,7 @@ Same as for `container` object (see [Events](#container-events) in the section [ | `layout` | `object` | The `layout` object that triggered the event | `width` | `number` | The fitted width of the `layout` object, in pixels -This event is triggered when the [fitted width](#fitted-size) of the `layout` object is calculated. Once this is triggered, the behavior can modify the coordinates of its contents. Returns the fitted width of the `layout` object, in pixels. +This event is triggered when the [fitted width](#fitted-size) of the `layout` object is calculated. Once this is triggered, the behavior can modify the coordinates of its contents. Returns the fitted width of the `layout` object, in pixels. *** @@ -2721,22 +2721,22 @@ Prototype inherits from `Content.prototype`. **`drawContent(x, y, width, height) `** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y, width, height` | `number` | The local position and size of the area in which to draw, in pixels Draws this port's skin in the position specified ```javascript -let heartSkin = new Skin({ - texture: new Texture("heart.png"), +let heartSkin = new Skin({ + texture: new Texture("heart.png"), color: "red", - x: 0, y: 0, width: 60, height: 60, + x: 0, y: 0, width: 60, height: 60, }); let sampleStyle = new Style({ font:"600 28px Open Sans", color: ["red", "yellow", "green", "blue"] }); let samplePort = new Port(null, { top: 0, bottom: 0, left: 0, right: 0, - skin: heartSkin, + skin: heartSkin, Behavior: class extends Behavior { onDraw(port) { let size = 60; @@ -2757,7 +2757,7 @@ application.add(samplePort); **`drawLabel(string, x, y, width, height)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `string ` | `string ` | The string to draw | `x, y, width, height` | `number` | The local position and size of the area in which to draw, in pixels @@ -2786,7 +2786,7 @@ application.add(samplePort); **`drawSkin(skin, x, y, width, height [, variant, state])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `skin ` | `skin ` | The skin to draw | `x, y, width, height` | `number` | The local position and size of the area in which to draw, in pixels | `variant` | `number` | The variant of the skin to draw. If the specified skin defines variants, setting the variant changes the appearance. @@ -2795,10 +2795,10 @@ application.add(samplePort); Draws the skin the way a `content` instance would, with the state, variant, and position specified. ```javascript -let heartSkin = new Skin({ - texture: new Texture("heart.png"), +let heartSkin = new Skin({ + texture: new Texture("heart.png"), color: ["red", "blue"], - x: 0, y: 0, width: 60, height: 60, + x: 0, y: 0, width: 60, height: 60, }); let samplePort = new Port(null, { @@ -2806,7 +2806,7 @@ let samplePort = new Port(null, { skin: new Skin({ fill: "white" }), Behavior: class extends Behavior { onDraw(port) { - port.drawSkin(heartSkin, 20, 20, 60, 60, 0, 1); + port.drawSkin(heartSkin, 20, 20, 60, 60, 0, 1); } } }) @@ -2820,7 +2820,7 @@ application.add(samplePort); **`drawString(string, style, color, x, y, width, height)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `string` | `string` | The string to draw | `style` | `style` | The style to use to draw the string | `color` | `string` | The color to draw the string, as a string of the form specified in the [Color](#color) section of this document @@ -2850,7 +2850,7 @@ application.add(samplePort); **`drawStyle(string, style, x, y, w, h [, ellipsis, state])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `string` | `string` | The string to draw | `style` | `style` | The style to use to draw the string | `x, y, width, height` | `number` | The local position and size of the area in which to draw, in pixels @@ -2863,7 +2863,7 @@ Draws a string with the style, position, and state specified. let sampleStyle = new Style({ font:"600 28px Open Sans", color: ["red", "yellow", "green", "blue"] }); let samplePort = new Port(null, { top: 0, bottom: 0, left: 0, right: 0, - skin: new Skin({ fill: "white" }), + skin: new Skin({ fill: "white" }), Behavior: class extends Behavior { onDraw(port) { let string = "Hello, World!"; @@ -2947,7 +2947,7 @@ application.add(samplePort); **`fillTexture(texture, color, x, y, width, height, sx, sy, sw, sh)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `texture ` | `texture` | The filling image | `x, y, width, height` | `number` | The destination area--the local position and size of the area to copy pixels to, in pixels | `sx, sy, sw, sh` | `number` | The source area--the position and size of the area to copy pixels from, in pixels. @@ -2979,7 +2979,7 @@ application.add(samplePort); **`invalidate([x, y, width, height])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `x, y, width, height` | `number` | The local position and size of the area to invalidate, in pixels Invalidates the specified area of this port (or the entire port if no area is specified), which triggers the `onDraw` event. @@ -3011,7 +3011,7 @@ application.add(samplePort); **`measureString(string, style)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `string` | `string` | The string to measure | `style` | `style` | The style to use when measuring the string @@ -3055,7 +3055,7 @@ Restores the current clip rectangle from this port's clip rectangles stack **`pushClip([x, y, width, height])`** | Argument | Type | Description | -| --- | --- | --- +| --- | --- | --- | `x, y, width, height` | `number` | The local position and size of the clip rectangle Saves the specified clip rectangle to this port's clip rectangles stack @@ -3186,7 +3186,7 @@ import { VerticalScrollerBehavior } from "scroller"; // See "scroller.js" from t let sampleStyle = new Style({ font:"600 28px Open Sans", color: "white" }); let scrollerSample = new Scroller(null, { - left: 0, right: 0, top: 0, bottom: 0, + left: 0, right: 0, top: 0, bottom: 0, style: sampleStyle, skin: new Skin({ fill: "blue" }), active: true, backgroundTouch: true, clip: true, Behavior: VerticalScrollerBehavior, @@ -3233,7 +3233,7 @@ let ScrollerSample = Scroller.template($ => ({ })); let screenWithScrollerSample = new Column(null, { top: 0, bottom: 0, left: 0, right: 0, - style: sampleStyle, + style: sampleStyle, contents: [ Text(null, { top: 0, height: 40, left: 0, right: 0, @@ -3294,7 +3294,7 @@ let ScrollerItem = Label.template($ => ({ style: sampleStyle, string: "Item" + $ })); let scrollerSample = new Scroller(null, { - left: 0, right: 0, top: 0, bottom: 0, + left: 0, right: 0, top: 0, bottom: 0, skin: new Skin({ fill: "black" }), Behavior: SampleScrollerBehavior, contents:[ @@ -3340,7 +3340,7 @@ let ColoredSquare = Content.template($ => ({ skin: new Skin({ fill: $ }) })); let scrollerSample = new Scroller(null, { - left: 0, right: 0, top: 0, bottom: 0, + left: 0, right: 0, top: 0, bottom: 0, skin: new Skin({ fill: "black" }), active: true, backgroundTouch: true, clip: true, Behavior: SampleScrollerBehavior, @@ -3389,7 +3389,7 @@ let ColoredSquare = Content.template($ => ({ } })); let scrollerSample = new Scroller(null, { - left: 0, right: 0, top: 0, bottom: 0, + left: 0, right: 0, top: 0, bottom: 0, skin: new Skin({ fill: "black" }), contents:[ Column(null, { @@ -3420,10 +3420,10 @@ Same as for `container` object (see [Events](#container-events) in the section [ ##### `onScrolled(scroller)` | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `scroller` | `scroller` | The `scroller` object that triggered the event -This event is triggered when the specified `scroller` object scrolls. +This event is triggered when the specified `scroller` object scrolls. When triggered by a scroller, this event is also triggered by all the contents of the scroller. This makes it easier to implement scrollbars, for example. @@ -3468,7 +3468,7 @@ application.add(borderedContent); ##### `Skin.template([dictionary])` | Arguments | Type | Description -| --- | --- | --- +| --- | --- | --- | `dictionary` | `object` | An object with properties to initialize the result. Only parameters specified in the [Dictionary](#skin-dictionary) section below will have an effect; other parameters will be ignored. Returns a constructor, a function that creates instances of `Skin.prototype`. The `prototype` property of the result is `Skin.prototype`. @@ -3619,7 +3619,7 @@ Sound.close(); **`play([stream, repeat, callback]) `** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `stream` | `number` | The stream to play the sound on. Defaults to `0`. | `repeat` | `number` | The number of times to repeat the sound. Defaults to `1`. Set the `repeat` property to `Infinity` to repeat the sound indefinitely. | `callback` | `function` | An optional callback function to invoke after the audio resource completes playback. @@ -3631,7 +3631,7 @@ Plays the audio sample on the specified stream `repeat` times. If the `callback` sampleSound.play(); // Play sampleSound 5 times -sampleSound.play(0, 5); +sampleSound.play(0, 5); // Play sampleSound once and print to the console when finished sampleSound.play(0, 1, () => { @@ -3661,7 +3661,7 @@ Returns `style` instance, an object that inherits from `Style.prototype` ```javascript let sampleStyle = new Style({ font:"600 28px Open Sans", color: "blue" }); let sampleLabel = new Label(null, { - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), style: sampleStyle, string: "Hello, World!" }); @@ -3682,12 +3682,12 @@ Returns a constructor, a function that creates instances of `Style.prototype`. T let RedStyle = Style.template({ font:"600 28px Open Sans", color: "red" }); let BlueStyle = Style.template({ font:"600 28px Open Sans", color: "blue" }); let sampleLabel = new Label(null, { - top: 0, height:30, left: 0, right: 0, + top: 0, height:30, left: 0, right: 0, skin: new Skin({ fill: "white" }), Style: RedStyle, string: "Hello, World!" // Note the capital "S" in "Style" }); let sampleLabel2 = new Label(null, { - top: 30, height: 30, left: 0, right: 0, + top: 30, height: 30, left: 0, right: 0, skin: new Skin({ fill: "white" }), style: new BlueStyle, string: "Hello, World!" // Note the lowercase "s" in "style" }); @@ -3731,7 +3731,7 @@ application.add(sampleLabel2); #### Prototype Description Prototype inherits from `Object.prototype`. - + ##### Properties All properties of a `style` object are read-only, but you can change the style of content objects at any time. @@ -3773,7 +3773,7 @@ let size = normalStyle.measure("Moddable"); // {"width":134,"height":38} ``` *** - + ### Text Object - **Source code:** [`piuText.c`][15] @@ -3964,7 +3964,7 @@ Returns a `texture` instance, an object that inherits from `Object.prototype` const logoTexture = new Texture({ path: "logo.png" }); const logoSkin = new Skin({ texture: logoTexture, x: 0, y: 0, width: 100, height: 20 }); ``` - + ##### `Texture.template(dictionary)` | Argument | Type | Description | @@ -3990,7 +3990,7 @@ const AnotherLogoSkin = Skin.template({ texture: new AnotherLogoTexture(), x: 0, | Parameter | Type | Description | | --- | --- | :--- | | `path` | `string` | The URL of the image file. It must be a file URL. - + #### Prototype Description Prototype inherits from `Object.prototype`. @@ -3999,7 +3999,7 @@ Prototype inherits from `Object.prototype`. | Name | Type | Read Only | Description | | --- | --- | --- | :--- | -| `height` | `number` | ✓ | This texture's height, in physical pixels           +| `height` | `number` | ✓ | This texture's height, in physical pixels           | `width` | `number` | ✓ | This texture's width, in physical pixels ### Timeline Object @@ -4043,14 +4043,14 @@ let timeline = new Timeline(); ##### Functions - **`from(target, fromProperties, duration, [easing, delay])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `target` | `object` | The object that will have its properties tweened by the timeline. | `fromProperties` | `object` | The keys of this object are the properties of the `target` object that will be tweened by the timeline. Their values are the starting values the properties of the `target` object will have at the begining of the tween. | `duration` | `number` | The duration of the tween in ms. @@ -4064,7 +4064,7 @@ Returns this timeline, useful for chaining together multiple `to`, `from`, and ` ```javascript let sampleStyle = new Style({ font: "600 28px Open Sans", color: ["blue", "white"] }); let sampleColumn = new Column(null, { - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), style: sampleStyle, contents: [ Label(null, { top: 90, height: 28, left: 80, string: "Hello", state: 0 }), @@ -4093,7 +4093,7 @@ application.add(sampleColumn); **`on(target, onProperties, duration, easing, delay, when)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `target` | `object` | The object that will have its properties tweened by the timeline. | `onProperties` | `object` | The keys of this object are the properties of the `target` object that will be tweened by the timeline. Their values are arrays of values that the tween will ease between over the duration of the timeline. | `duration` | `number` | The duration of the tween in ms. @@ -4142,7 +4142,7 @@ application.add(sampleContainer); **`seekTo(time)`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `time` | `number` | The position in the Timeline to seek to. Causes this timeline to jump its tweens to the specified time. This sets the properties of the tweens' target objects. @@ -4150,7 +4150,7 @@ Causes this timeline to jump its tweens to the specified time. This sets the pro **`to(target, toProperties, duration, [easing, delay])`** | Argument | Type | Description | -| --- | --- | :--- | +| --- | --- | :--- | | `target` | `object` | The object that will have its properties tweened by the timeline. | `toProperties` | `object` | The keys of this object are the properties of the `target` object that will be tweened by the timeline. Their values are the destination values the properties of the `target` object will have when the tween is complete. | `duration` | `number` | The duration of the tween in ms. @@ -4164,7 +4164,7 @@ Returns this timeline, useful for chaining together multiple `to`, `from`, and ` ```javascript let sampleStyle = new Style({ font: "600 28px Open Sans", color: ["blue", "white"] }); let sampleColumn = new Column(null, { - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: "white" }), style: sampleStyle, contents: [ Label(null, { top: 90, height: 28, left: 80, string: "Hello", state: 0 }), @@ -4195,7 +4195,7 @@ application.add(sampleColumn); - **Source code:** [`piuTransition.c`][17] - **Relevant Examples:** N/A -The `transition` object is used to animate modifications of the containment hierarchy. +The `transition` object is used to animate modifications of the containment hierarchy. #### Constructor Description @@ -4241,11 +4241,11 @@ class SwitchScreenBehavior extends Behavior { } } let ColoredScreen = Container.template($ => ({ - top: 0, bottom: 0, left: 0, right: 0, + top: 0, bottom: 0, left: 0, right: 0, skin: new Skin({ fill: $.color }), contents: [ Content($, { - active: true, height: 100, width: 100, + active: true, height: 100, width: 100, skin: new Skin({ fill: $.nextColor }), Behavior: SwitchScreenBehavior }) diff --git a/documentation/readme.md b/documentation/readme.md index 05107e0c14..1e7ca919d6 100644 --- a/documentation/readme.md +++ b/documentation/readme.md @@ -22,10 +22,10 @@ Guides for working with specific microcontrollers supported by the Moddable SDK The JavaScript APIs for the modules in the Moddable SDK are documented in the following files: - [**Base**](./base/base.md): Fundamental runtime capabilities including time, timer, debug, instrumentation, and UUID - - [**Setup**](./base/setup.md): Using `setup` modules to configure a host before other modules execute - - [**Worker**](./base/worker.md): Using Web Workers and Shared Workers + - [**Setup**](./base/setup.md): Using `setup` modules to configure a host before other modules execute + - [**Worker**](./base/worker.md): Using Web Workers and Shared Workers - [**Commodetto**](./commodetto/commodetto.md): Bitmap graphics library including parsing and rendering of BMP, JPEG, and PNG images, and BMFont files; classes for operating on bitmaps, and pixel format conversion - - [**Poco**](./commodetto/poco.md): Examples and reference for using the JavaScript and C APIs of the Poco renderer + - [**Poco**](./commodetto/poco.md): Examples and reference for using the JavaScript and C APIs of the Poco renderer - [**Crypt**](./crypt/crypt.md): Cryptographic primitives - [**Data**](./data/data.md): Base64 and hex encoding and decoding - [**Files**](./files/files.md): Storage capabilities including files, flash, preferences, resources, and ZIP diff --git a/documentation/tools/defines.md b/documentation/tools/defines.md index 9c67fc304f..84f4381193 100644 --- a/documentation/tools/defines.md +++ b/documentation/tools/defines.md @@ -82,8 +82,8 @@ To support option #defines, the driver implementation provides default values an #define MODDEF_ILI9341_FLIPY (false) #endif -Many deployments do not need to reset the ILI9341 display explicitly, as the automatic reset at power-up is sufficient. The reset pin has a behavior which is only implemented when the reset pin is defined in the manifest. - +Many deployments do not need to reset the ILI9341 display explicitly, as the automatic reset at power-up is sufficient. The reset pin has a behavior which is only implemented when the reset pin is defined in the manifest. + #ifdef MODDEF_ILI9341_RST_PIN SCREEN_RST_INIT; SCREEN_RST_ACTIVE; diff --git a/documentation/tools/manifest.md b/documentation/tools/manifest.md index 3b290af634..6831adb342 100644 --- a/documentation/tools/manifest.md +++ b/documentation/tools/manifest.md @@ -75,22 +75,22 @@ When you build an application, the default output directory name is taken from t "NAME": "balls" } ``` - + #### ESP32-specific environment variables The `esp32` platform object supports a number of optional environment variables applications can use to customize the Moddable SDK build for ESP32 devices: | Variable | Description | -| --- | :--- | +| --- | :--- | | `ESP32_SUBCLASS` | If a device other than the `esp32`, set `esp32s2`, `esp32s3` or `esp32c3` -| `SDKCONFIGPATH` | Pathname to a directory containing custom [sdkconfig defaults](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#custom-sdkconfig-defaults) entries. +| `SDKCONFIGPATH` | Pathname to a directory containing custom [sdkconfig defaults](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#custom-sdkconfig-defaults) entries. | `PARTITIONS_FILE` | Pathname to a [partition table](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html) in CSV format. | `BOOTLOADERPATH` | Pathname to a directory containing a custom [ESP-IDF bootloader component](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/bootloader.html#custom-bootloader). | `C_FLAGS_SUBPLATFORM` | C compiler flags to use when compiling Moddable SDK sources. -| `USE_USB` | Configure the device to use the USB port for programming and debugging. +| `USE_USB` | Configure the device to use the USB port for programming and debugging. > Note: This document does not cover native code ESP32 and ESP-IDF build details. Refer to the [ESP-IDF documentation](https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/get-started/index.html) for additional information. - + #### `ESP32_SUBCLASS` The target ESP32 subclass for a build is specified using the `ESP32_SUBCLASS` property. @@ -239,12 +239,12 @@ The default value of the `"include"` property is `"manifest.json"`. The `"includ { "git":"$(URL)/test0.git" }, - { - "git":"$(URL)/test1.git", + { + "git":"$(URL)/test1.git", "include":"modules/test1/manifest.json" }, - { - "git":"$(URL)/test23.git", + { + "git":"$(URL)/test23.git", "include": [ "test2/module.json", "test3/module.json" @@ -391,8 +391,8 @@ The `strip` object in a manifest is a string or array that specifies which built ```json "strip": "*", ``` - -- If you only want certain objects or functions to be stripped, pass in an array of JavaScript class and function names. Items in the array will be stripped. Anything not included in the array will not be stripped. + +- If you only want certain objects or functions to be stripped, pass in an array of JavaScript class and function names. Items in the array will be stripped. Anything not included in the array will not be stripped. The following strips the `RegExp` class, `eval` function, and the two `Array` reduce functions. @@ -408,7 +408,7 @@ The `strip` object in a manifest is a string or array that specifies which built - You can also specify that specific items be stripped in addition to anything unused. The `"*"` means to strip everything unused. Because the two `Array` reduce functions are explicitly listed, they will also be stripped, whether or not they are used. - + ```json "strip": [ "*", @@ -743,8 +743,8 @@ The second pass matches files with the properties of the combined `modules` and There are no extensions: -- In the `modules` object, `mcconfig` matches `.c`, `.cc`, `.cpp`, `.h`, `.js` and `.m` files. -- In the `resources` object, `mcconfig` matches `.act`, `.bmp`, `.cct`, `.dat`, `.der`, `.fnt`, `.jpg`, `.json`, `.nfnt`, `.pk8`, `.png`, `.rle`, `.ski` and `.ttf` files. +- In the `modules` object, `mcconfig` matches `.c`, `.cc`, `.cpp`, `.h`, `.js` and `.m` files. +- In the `resources` object, `mcconfig` matches `.act`, `.bmp`, `.cct`, `.dat`, `.der`, `.fnt`, `.jpg`, `.json`, `.nfnt`, `.pk8`, `.png`, `.rle`, `.ski` and `.ttf` files. ### Generate diff --git a/documentation/tools/testing.md b/documentation/tools/testing.md index 00b5fb4688..593a9455a0 100644 --- a/documentation/tools/testing.md +++ b/documentation/tools/testing.md @@ -52,11 +52,11 @@ The TEST262 tests are located in a repository on GitHub. git clone https://github.com/tc39/test262 ``` -> Note: The `xst` tool may be used to [run test262 tests](../xs/xst.md#test262) on the local computer from the command line. +> Note: The `xst` tool may be used to [run test262 tests](../xs/xst.md#test262) on the local computer from the command line. ### Moddable SDK Tests -The Moddable SDK tests are a suite of tests created by Moddable to validate the correctness and consistency the implementations across different device targets. The tests cover a wide range of functionality including hardware I/O, networking, graphics, data, and more. Because of differences in hardware capabilities and features supported in each port, not all tests will pass in all environments. +The Moddable SDK tests are a suite of tests created by Moddable to validate the correctness and consistency the implementations across different device targets. The tests cover a wide range of functionality including hardware I/O, networking, graphics, data, and more. Because of differences in hardware capabilities and features supported in each port, not all tests will pass in all environments. The Moddable SDK tests are located in the Moddable SDK repository at `$MODDABLE/tests`. @@ -117,7 +117,7 @@ Clicking to the left of a category or individual test selects that test or categ -You may also use the `SELECT` text field to type in the name of the test(s) that you would like to run. +You may also use the `SELECT` text field to type in the name of the test(s) that you would like to run. ### Run Tests @@ -210,7 +210,7 @@ flags: [module] assert.sameValue("Java" + "Script", "JavaScript"); ``` -The `module` flag tells the test runner that the test should loaded as an ECMAScript module, not a program. If the `module` flag is not present, the test is run as a program. All tests written for the Moddable SDK should include the `module` flag because nearly all scripts in the Moddable SDK are executed as modules. +The `module` flag tells the test runner that the test should loaded as an ECMAScript module, not a program. If the `module` flag is not present, the test is run as a program. All tests written for the Moddable SDK should include the `module` flag because nearly all scripts in the Moddable SDK are executed as modules. In addition to flags, the frontmatter may contain a short description of the test or a longer informational section: @@ -226,7 +226,7 @@ flags: [module] ---*/ ``` -The frontmatter is required. If it is not present, the test script will not be executed. If the frontmatter is incorrect, the test script may not run correctly. +The frontmatter is required. If it is not present, the test script will not be executed. If the frontmatter is incorrect, the test script may not run correctly. By convention, the copyright notice appears immediately before or after the frontmatter, but always before the test script. @@ -330,7 +330,7 @@ flags: [module,async] $TESTMC.timeout(500, "timeout on promise resolve"); ``` -Asynchronous tests are more difficult to write than synchronous tests, just as asynchronous code is more challenging to write than synchronous code When getting started, take care and try to follow the patterns of existing tests that already work. +Asynchronous tests are more difficult to write than synchronous tests, just as asynchronous code is more challenging to write than synchronous code When getting started, take care and try to follow the patterns of existing tests that already work. ### Assertions @@ -413,7 +413,7 @@ The tests in TEST262 itself are are often just a few lines of code. Keeping test ### Minimize Assumptions about the Environment -Each test is run in a fresh virtual machine. This helps to ensure consistent test results because each test executes independently of the tests that ran before it. But there are limits to how much a test can be isolated from those that ran earlier. +Each test is run in a fresh virtual machine. This helps to ensure consistent test results because each test executes independently of the tests that ran before it. But there are limits to how much a test can be isolated from those that ran earlier. A test for the file system will create, delete, and modify files. Such tests should clean-up after themselves, by removing any temporary files. However, this is imperfect. If the test fails, it will not have a chance to clean-up. Therefore, in general tests should be written so they work even if previous tests did not properly clean-up. @@ -469,7 +469,7 @@ Image checksums also work with screens generated by the Piu user interface frame ```js /*--- -description: +description: flags: [module] ---*/ import Bitmap from "commodetto/Bitmap"; @@ -498,7 +498,7 @@ The following test sends a touch begin event. The behavior confirms that the exp ```js /*--- -description: +description: flags: [async, module] ---*/ class TouchTestBehavior extends $TESTMC.Behavior { @@ -507,7 +507,7 @@ class TouchTestBehavior extends $TESTMC.Behavior { assert.sameValue(x, 10); assert.sameValue(y, 20); $DONE(); - } + } } new Application(null, { @@ -536,7 +536,7 @@ $TESTMC.timeout(5000, "dns lookup timeout"); ``` #### `HostObject`, `HostObjectChunk`, `HostBuffer` -These constructors are used to create host objects to pass as arguments to functions being tested. +These constructors are used to create host objects to pass as arguments to functions being tested. ```js new $TESTMC.HostObject // host object with pointer (-1) for storage @@ -634,11 +634,11 @@ await screen.doTouchBegan(0, 100, 100, Time.ticks); ``` #### Test Configuration in `mc/config` -The testmc manifest contains configuration values for on-device testing, such as hardware pin numbers and I/O ports. These values are used by tests, so that they may written to be independent of the device being tested. When running testmc on a new device, the configuration values for the device must be added to the manifest. +The testmc manifest contains configuration values for on-device testing, such as hardware pin numbers and I/O ports. These values are used by tests, so that they may written to be independent of the device being tested. When running testmc on a new device, the configuration values for the device must be added to the manifest. - `config.digital[]` -An array of ECMA-419 digital pin specifiers. +An array of ECMA-419 digital pin specifiers. - `config.i2c` @@ -654,7 +654,7 @@ An object with properties for SPI testing. `select` is the ECMA-419 pin specifie - `config.invalidPins` -An array of ECMA-419 pin specifiers that are invalid for the target device. +An array of ECMA-419 pin specifiers that are invalid for the target device. - `config.flashPartition` diff --git a/documentation/tools/tools.md b/documentation/tools/tools.md index e6f356f498..f9ba3cf925 100644 --- a/documentation/tools/tools.md +++ b/documentation/tools/tools.md @@ -6,7 +6,7 @@ Revised: March 23, 2023 This document describes the tools provided by Moddable to build, debug, and run JavaScript apps on microcontrollers or in the Moddable simulator. -The tools compile and link JavaScript modules, and prepare assets for specific platforms and specific screens. The only tools you use directly are **mcconfig**, **mcrun**, and **xsbug**. The other tools are used indirectly, through the make file generated by **mcconfig** and **mcrun**, but are nevertheless presented here to help you understand what is happening under the hood. +The tools compile and link JavaScript modules, and prepare assets for specific platforms and specific screens. The only tools you use directly are **mcconfig**, **mcrun**, and **xsbug**. The other tools are used indirectly, through the make file generated by **mcconfig** and **mcrun**, but are nevertheless presented here to help you understand what is happening under the hood. To build the tools themselves, and to build and run apps in the Moddable simulator, you only need standard development tools. To build and run apps on microcontrollers, you also need the microcontrollers toolchains to compile and link C code, and to transfer apps to flash storage. See the [Getting Started document](../Moddable%20SDK%20-%20Getting%20Started.md) for full instructions on how to build the Moddable SDK tools. @@ -24,7 +24,7 @@ To build the tools themselves, and to build and run apps in the Moddable simulat ## mcconfig -**mcconfig** is a command line tool that generates a make file based on a manifest, then runs **make** to build and launch Moddable apps on microcontrollers or in the simulator. +**mcconfig** is a command line tool that generates a make file based on a manifest, then runs **make** to build and launch Moddable apps on microcontrollers or in the simulator. For example: @@ -39,14 +39,14 @@ builds and launches the [balls example](../../examples/piu/balls) in the simulat cd $MODDABLE/examples/piu/balls mcconfig -d -m -p esp/moddable_two ``` - + builds and launches the balls example on Moddable Two, and ```shell cd $MODDABLE/examples/network/http/httpgetjson mcconfig -d -m -p esp ssid="Public Wi-Fi" ``` - + configures an ESP8266 target device to connect to an open Wi-Fi access point called "Public Wi-Fi," then build and launch the httpgetjson example on the device. A few notes: @@ -70,7 +70,7 @@ mcconfig [manifest] [-d] [-f format] [-i] [-m] [-o directory] [-p platform] [-r - `-x`: overrides the default host and port (localhost:5002) debug builds use to connect to xsbug. - `-m`: to run `make` automatically, otherwise **mcconfig** just generates the make file. - `-o directory`: the output directory. Defaults to the `$MODDABLE/build` directory. -- `-p platform`: to select the platform. Consult the documentation for your device target for its platform identifier. The supported values include: `esp`, `esp/moddable_one`, `esp/moddable_three`, `esp32`, `esp32/moddable_two`, `win`, `lin`, `mac`, `sim/moddable_one`, `sim/moddable_two`, `sim/moddable_three`, and `wasm`. Defaults to the host build platform:`mac`, `win` or `lin`. +- `-p platform`: to select the platform. Consult the documentation for your device target for its platform identifier. The supported values include: `esp`, `esp/moddable_one`, `esp/moddable_three`, `esp32`, `esp32/moddable_two`, `win`, `lin`, `mac`, `sim/moddable_one`, `sim/moddable_two`, `sim/moddable_three`, and `wasm`. Defaults to the host build platform:`mac`, `win` or `lin`. - `-r rotation`: to select the screen rotation: `0`, `90`, `180` or `270`. Defaults to `0`. See [png2bmp](#png2bmp) for more detail. - `-t target`: to select the build target: `build`, `deploy`, `xsbug`, `clean`, or `all`. Defaults to `all`. See [Build Targets](#buildtargets) for more detail. - `-v`: to trace all commands executed by `make` @@ -169,7 +169,7 @@ png2bmp balls.png -o ~/Desktop -f gray256 -r 90 ### Arguments -```text +```text png2bmp file.png [-a] [-c] [f format] [-o directory] [-r rotation] ``` @@ -182,7 +182,7 @@ png2bmp file.png [-a] [-c] [f format] [-o directory] [-r rotation] ## xsc -**xsc** is the XS compiler, a command line tool that compiles files containing JavaScript source code (usually stored in a file with a `.js` extension) into XS binary files containing symbols and byte codes. +**xsc** is the XS compiler, a command line tool that compiles files containing JavaScript source code (usually stored in a file with a `.js` extension) into XS binary files containing symbols and byte codes. By default **xsc** parses the JavaScript file as an ECMAScript module. Optionally, for compatibility and conformance, **xsc** can parse the JavaScript file as an ECMAScript program. Moddable apps only use ECMAScript modules. @@ -201,7 +201,7 @@ The `Point` class creates host objects. The `Point_destructor` C function is cal Without the `-e` option, **xsc** generates C code that declares XS symbols and the interface of the host functions. Such C code can then be compiled and linked with the implementation of the host functions to build a dynamic library. -With the `-e` option, **xsc** embeds the references to host functions and host objects into the XS binary file. It is the linker, **xsl**, that generates C code for all the modules. That is how Moddable apps work. +With the `-e` option, **xsc** embeds the references to host functions and host objects into the XS binary file. It is the linker, **xsl**, that generates C code for all the modules. That is how Moddable apps work. ### Arguments @@ -223,7 +223,7 @@ xsc file [-c] [-d] [-e] [-o directory] [-p] [-r name] [-t directory] **xsl** is the XS linker, a command line tool that links several XS binary files into one XS archive file, and generates C code that declares XS symbols and the interface of the host functions. -With the `-p` option, **xsl** can also preload modules and generate C code that defines a read-only XS virtual machine suitable to be cloned to run apps. That is how Moddable apps work. +With the `-p` option, **xsl** can also preload modules and generate C code that defines a read-only XS virtual machine suitable to be cloned to run apps. That is how Moddable apps work. The C code can then be compiled and linked with the implementation of the host functions to build a dynamic library or an executable. @@ -234,9 +234,9 @@ xsl files... [-a name] [-b directory] [c creation] [-o directory] [-p modules].. ``` - `files`: the paths of the XS binary files to link. -- `-a name`: the name of the XS archive file. Defaults to `a`. +- `-a name`: the name of the XS archive file. Defaults to `a`. - `-b directory`: the path of the base directory. Defaults to the output directory. The names of the modules in the archive are the paths of the XS binary files, relative to the base directory. It is an error to link XS binary files which are not directly or indirectly inside the base directory. -- `-c creation`: the parameters used to create the cloned machines. +- `-c creation`: the parameters used to create the cloned machines. - `-o directory`: the path of the output directory. Defaults to the current directory. - `-p module`: the name of a module to preload. Use one `-p module` option by module to preload. - `-r name`: the name of the output file. Defaults to `mc`. @@ -297,7 +297,7 @@ The shell script, the app archive folder, and the app archive file are located i ### Arguments ```text -mcbundle [manifest] [-d] [-m] [-o directory] +mcbundle [manifest] [-d] [-m] [-o directory] ``` - `manifest`: the manifest file. Defaults to the `manifest.json` file in the current directory. diff --git a/documentation/xs/ROM Colors.md b/documentation/xs/ROM Colors.md index 7c269fc0e5..9b6d25caf0 100644 --- a/documentation/xs/ROM Colors.md +++ b/documentation/xs/ROM Colors.md @@ -6,7 +6,7 @@ Revised: August 12, 2020 In XS, instances are mostly linked list of properties with a key and a value. To get a value by key, the runtime iterates the linked list to find a property with a matching key. -Of course XS already implements several optimizations to access properties by index: in array instances, in closures, in global and local scopes. +Of course XS already implements several optimizations to access properties by index: in array instances, in closures, in global and local scopes. The XS linker prepares most classes, objects, prototypes, functions to be accessed straightly from ROM. Such instances and their properties never change. That is an opportunity to access properties by index, especially since iterating a linked list in ROM is not optimal. @@ -22,7 +22,7 @@ The technique is based on graph coloring. Similar techniques are applied to obje When intrinsics and all modules are preloaded, the XS linker traverses all instances and their properties to build a conflict graph. The nodes are the keys, the edges are the conflicts. Two keys conflict if there is an instance that has properties for both keys. Choosing indexes for keys is equivalent to coloring nodes in the graph. -Once the graph is colored, each key has a color that can be used to access a property by index. +Once the graph is colored, each key has a color that can be used to access a property by index. property = instance[key.color] @@ -30,9 +30,9 @@ Since non conflicting keys can reuse the same color, the runtime has to check if if (property.key == key) return property - -Optimal graph coloring could be complex, but coloring from the most to the least conflicted key usually gives good enough results: the number of colors is significantly smaller than the number of keys. - + +Optimal graph coloring could be complex, but coloring from the most to the least conflicted key usually gives good enough results: the number of colors is significantly smaller than the number of keys. + ## Memory Layout What remains to be done is to reorganize the ROM so properties are where the color of their key wants them to be. @@ -97,11 +97,11 @@ Eventually instances are moved to fill the holes. Now the two objects are intertwined to reduce the memory footprint. There are usually enough instances without properties or with a few properties to fill all holes. -> Despite all movements, the order of the linked lists is maintained. That is required by several object traversal functions. +> Despite all movements, the order of the linked lists is maintained. That is required by several object traversal functions. ## Results -Here is a simple test. +Here is a simple test. const math = Math; const now = Date.now(); @@ -115,7 +115,7 @@ Here is a simple test. -The `Math` object is in ROM and its `imul`, `max`, `min` and `sign` properties are accessed 100000 times. The `Math` object is cached into a `const` to avoid the interference of global scope optimizations, the properties are selected to avoid floating point operations. +The `Math` object is in ROM and its `imul`, `max`, `min` and `sign` properties are accessed 100000 times. The `Math` object is cached into a `const` to avoid the interference of global scope optimizations, the properties are selected to avoid floating point operations. Here are results without and with the optimization: diff --git a/documentation/xs/XS Compartment.md b/documentation/xs/XS Compartment.md index 86aa576fd2..ae887dd678 100644 --- a/documentation/xs/XS Compartment.md +++ b/documentation/xs/XS Compartment.md @@ -8,9 +8,9 @@ XS implements most of the [TC39 Compartment Proposal](https://github.com/tc39/pr In XS, the real host is the application that creates an XS machine to evaluate scripts and import modules. -Compartments are lightweight virtual hosts that evaluate scripts and import modules separately from the real host and from other compartments. +Compartments are lightweight virtual hosts that evaluate scripts and import modules separately from the real host and from other compartments. -Compartments have their own `globalThis` object, their own global lexical scope and their own module map. +Compartments have their own `globalThis` object, their own global lexical scope and their own module map. > The module map binds module specifiers to modules. Inside compartments like inside the real host, the same module specifier always imports the same module. @@ -22,8 +22,8 @@ By default: Compartments run in the same XS machine: -- Except for `Compartment`, `Function` and `eval`, built-ins are shared. -- Other objects can be shared thru the `globals` and `globalLexicals` options. +- Except for `Compartment`, `Function` and `eval`, built-ins are shared. +- Other objects can be shared thru the `globals` and `globalLexicals` options. - Modules can be shared thru the `modules`, `loadHook` and `loadNowHook` options. For the sake of security, it is the responsibility of a real host that creates compartments to ensure that shared features are immutable. @@ -49,13 +49,13 @@ XS implements compartments natively, without `Module` and `Evaluators` classes, #### Compartment(options) -Returns a compartment, an instance of `Compartment.prototype`. +Returns a compartment, an instance of `Compartment.prototype`. If present, the `options` argument must be an object with optional properties: `globals`, `globalLexicals`, `modules`, `loadHook`, `loadNowHook`, `resolveHook`. #### options.globals -The `globals` option adds properties to the compartment `globalThis` object. +The `globals` option adds properties to the compartment `globalThis` object. If defined, the value of the `globals` option must be an object. @@ -67,12 +67,12 @@ A compartment does not keep a reference to the `globals` object. The `globalLexicals` option initializes the compartment global lexical scope. -If defined, the value of the `globalLexicals` option must be an object. +If defined, the value of the `globalLexicals` option must be an object. Each own enumerable named property of the `globalLexicals ` object become a variable or a constant: - property names are variable or constant names, -- property values are variable or constant values. +- property values are variable or constant values. If the property is writable, a variable (`let`) is created, else a constant (`const`) is created. @@ -82,7 +82,7 @@ A compartment does not keep a reference to the `globalLexicals` object. The `modules` option initializes the compartment module map. -If defined, the value of the `modules` option must be an object. +If defined, the value of the `modules` option must be an object. Each own enumerable named property of the `modules` object creates an entry in the compartment module map: @@ -99,7 +99,7 @@ The `loadHook` option is an asynchronous function that takes a module specifier The `loadHook` function is only called directly or indirectly by `Compartment.prototype.import` if the module map of the compartment has no entry for a module specifier. -The `loadHook` function is useful if the module descriptor is unavailable when constructing the compartment, or to create a module descriptor dynamically. +The `loadHook` function is useful if the module descriptor is unavailable when constructing the compartment, or to create a module descriptor dynamically. A compartment keeps a reference to the `loadHook` function. @@ -109,7 +109,7 @@ The `loadNowHook` option is a function that takes a module specifier and returns The `loadNowHook` function is only called directly or indirectly by `Compartment.prototype.importNow` if the module map of the compartment has no entry for a module specifier. -The `loadNowHook ` function is useful if the module descriptor is unavailable when constructing the compartment, or to create a module descriptor dynamically. +The `loadNowHook ` function is useful if the module descriptor is unavailable when constructing the compartment, or to create a module descriptor dynamically. A compartment keeps a reference to the `loadNowHook ` function. @@ -173,7 +173,7 @@ The initial value of this property is the `"Compartment"` string. Returns a module source, an instance of `ModuleSource.prototype`. -The source argument is coerced into a string, then parsed as a module and compiled into byte codes. +The source argument is coerced into a string, then parsed as a module and compiled into byte codes. XS does not keep a reference to the `source` string. @@ -201,7 +201,7 @@ The initial value of this property is the `"ModuleSource"` string. ### Module Descriptor -Comparments can load and initialize module namespaces from module descriptors. Like property descriptors, module descriptors are ordinary objects with various forms. +Comparments can load and initialize module namespaces from module descriptors. Like property descriptors, module descriptors are ordinary objects with various forms. #### descriptors with `source`, `importMeta` and `specifier` properties @@ -213,26 +213,26 @@ Comparments can load and initialize module namespaces from module descriptors. L If the `importMeta` property is present, its value must be an object. The default `importMeta` object is an empty object. -Compartments copy the `importMeta` object properties into the module `import.meta` object like `Object.assign`. +Compartments copy the `importMeta` object properties into the module `import.meta` object like `Object.assign`. If the `specifier` property is present, its value is coerced into a string and becomes the referrer specifier of the module. #### descriptors with `namespace` and `compartment` properties -- If fhe value of the `namespace` property is a string, the descriptor shares a module to be loaded and initialized by the compartment referred by the `compartment` property. +- If fhe value of the `namespace` property is a string, the descriptor shares a module to be loaded and initialized by the compartment referred by the `compartment` property. - If the `compartment` property is present, its value must be a compartment. - If absent, the `compartment` property defaults to the compartment being constructed in the `modules` option, or being hooked in the `loadHook` and `loadNowHook` options. - + - Else if the value of the `namespace ` property is a module namepace, the descriptor shares a module that is already available. - Else the value of `record` property must be an object. The module is loaded and initialized from the object according to the [virtual module namespace](#VirtualModuleNamespace) pattern. - + #### descriptor with `archive` and `path` properties -To construct a static module record from a [mod](./mods.md). In Moddable runtime, mods are separate archives of modules and resources. +To construct a static module record from a [mod](./mods.md). In Moddable runtime, mods are separate archives of modules and resources. -- The `archive` property must be an archive. +- The `archive` property must be an archive. - The `path` property is coerced into a string then used to find the module in the archive. ### Module Binding @@ -240,7 +240,7 @@ To construct a static module record from a [mod](./mods.md). In Moddable runtime A module binding is an ordinary object with properties that mimick the `import` and `export` constructs. There are many forms of module bindings. See the [imports](https://tc39.es/ecma262/#table-import-forms-mapping-to-importentry-records) and [exports](https://tc39.es/ecma262/#table-export-forms-mapping-to-exportentry-records) tables. -Most bindings can be represented as JSON-like objects with `export`, `import`, `as`, `from` properties. Except `*` bindings, which requires special forms because module namespace identifiers can be arbitrary. +Most bindings can be represented as JSON-like objects with `export`, `import`, `as`, `from` properties. Except `*` bindings, which requires special forms because module namespace identifiers can be arbitrary. | Construct | Module Binding | | :--- | :--- | @@ -253,13 +253,13 @@ Most bindings can be represented as JSON-like objects with `export`, `import`, ` | import x from "mod" | { import: "default", as: "x", from: "mod" } | import { x } from "mod" | { import: "x", from: "mod" } | import { x as y } from "mod" | { import: "x", as: "y", from: "mod" } -| import * as star from "mod" | { importAllFrom: "mod", as: "star" } +| import * as star from "mod" | { importAllFrom: "mod", as: "star" } ### Virtual Module Source A virtual module source is an ordinary object with `execute`, `bindings`, `needsImport` and `needsImportMeta` properties -- The `execute` property must be a function. +- The `execute` property must be a function. - If defined, the `bindings` property must be an array of [module bindings](#ModuleBinding). The default is an empty array. - If defined, the `needsImport` property is coerced into a boolean. The default is `false`. - If defined, the `needsImportMeta` property is coerced into a boolean. The default is `false`. @@ -272,7 +272,7 @@ Once the module is loaded and linked, the compartment calls the `execute` functi - `Import`: a function equivalent to the `import` call in a module body. The argument is `undefined` if `needsImport` was false. - `ImportMeta`: an object equivalent to the `import.meta` object in a module body. The argument is `undefined` if `needsImportMeta` was false. -The module environment record is sealed: +The module environment record is sealed: - no properties can be created or deleted, - export properties are writable, @@ -285,4 +285,4 @@ Like a module body, the `execute` function can be asynchronous. A virtual module namespace is an ordinary object posing as a module namespace. -When a compartment loads a virtual module namespace, each own enumerable named property of the object becomes an exported property of the module. +When a compartment loads a virtual module namespace, each own enumerable named property of the object becomes an exported property of the module. diff --git a/documentation/xs/XS Conformance.md b/documentation/xs/XS Conformance.md index f0faea92d5..3f6500b281 100644 --- a/documentation/xs/XS Conformance.md +++ b/documentation/xs/XS Conformance.md @@ -14,7 +14,7 @@ XS does not implement ECMA-402, the Internationalization API Specification, so t #### Annex B -No XS hosts are web browsers, so the `annexB` tests are skipped. However XS implements `Date.prototype.getYear`, `Date.prototype.setYear`, `Object.prototype.__defineGetter__`, `Object.prototype.__defineSetter__`, `Object.prototype.__lookupGetter__`, `Object.prototype.__lookupSetter__`, `Object.prototype.__proto__`, `String.prototype.substr`, `escape` and `unescape`, +No XS hosts are web browsers, so the `annexB` tests are skipped. However XS implements `Date.prototype.getYear`, `Date.prototype.setYear`, `Object.prototype.__defineGetter__`, `Object.prototype.__defineSetter__`, `Object.prototype.__lookupGetter__`, `Object.prototype.__lookupSetter__`, `Object.prototype.__proto__`, `String.prototype.substr`, `escape` and `unescape`, ## Runtime models @@ -23,7 +23,7 @@ On microcontrollers, XS uses a runtime model based on a virtual machine prepared Such a runtime model introduces no conformance issues in itself since XS can alias shared classes, functions and objects if apps modify them. However, in order to save ROM and RAM, other restrictions have been introduced: - Host functions, i.e. functions implemented in C, are primitive values like booleans, numbers, strings, etc. They are promoted to `Function` objects when necessary. -- Scripts evaluation is optional. So some platforms do not support `eval`, `new Function`, etc. But all platforms support `JSON.parse`. +- Scripts evaluation is optional. So some platforms do not support `eval`, `new Function`, etc. But all platforms support `JSON.parse`. - Optionnally the XS linker can dead strip ECMAScript built-ins that Moddable apps do not use, and remove `length` and `name` properties from functions. Here the conformance is tested on macOS with a traditional runtime model and without any restrictions. For each case, XS creates a virtual machine, then parses and runs the script. The XS harness, `xst`, uses [LibYAML](http://pyyaml.org/wiki/LibYAML) to load the frontmatter, which contains, among other information, the harness scripts to parse and run before the case script itself. @@ -34,17 +34,17 @@ To build `xst`: cd $MODDABLE/xs/makefiles/lin make - + #### macOS cd $MODDABLE/xs/makefiles/mac make - + #### Windows cd %MODDABLE%\xs\makefiles\win build - + To pass some tests, clone [test262](https://github.com/tc39/test262.git) and change the directory to the `test` directory inside the `test262` directory. Then you can run `xst` with files or directories. For instance: cd ~/test262/test @@ -1481,7 +1481,7 @@ Details are here under. The numbers of skipped cases are between parentheses. Th ## Failures -Here under are the failed tests. The comments are primarily here for the sake of future versions of XS. +Here under are the failed tests. The comments are primarily here for the sake of future versions of XS. ### Language @@ -1512,19 +1512,19 @@ Assignments should rename functions only if the left hand side is an identifier. The name of a function expression always defines a constant variable that reference the current function. In sloppy mode it should define a variable that can be assigned but does not change! language/expressions/object/literal-property-name-bigint.js - + XS does not support bigint as property name. - language/expressions/super/call-proto-not-ctor.js - + language/expressions/super/call-proto-not-ctor.js + XS checks if super is a constructor before evaluating arguments. language/statements/class/subclass/default-constructor-spread-override.js - + The default derived constructor should not use `%Array.prototype% @@iterator` - + language/statements/for-await-of/head-lhs-async.js - + `for (async of x)` is a syntax error but `for await (async of x)` should not be! language/statements/try/tco-catch.js (strict) @@ -1535,7 +1535,7 @@ XS does not tail call optimize `return` inside `catch` language/expressions/assignment/target-member-computed-reference-undefined.js language/identifier-resolution/assign-to-global-undefined.js -To be investigated. +To be investigated. ### Built-ins @@ -1548,26 +1548,26 @@ To be investigated. built-ins/RegExp/prototype/global/cross-realm.js built-ins/RegExp/prototype/ignoreCase/cross-realm.js built-ins/RegExp/prototype/multiline/cross-realm.js - built-ins/RegExp/prototype/source/cross-realm.js + built-ins/RegExp/prototype/source/cross-realm.js built-ins/RegExp/prototype/sticky/cross-realm.js built-ins/RegExp/prototype/unicode/cross-realm.js built-ins/Symbol/for/cross-realm.js built-ins/Symbol/for/cross-realm.js built-ins/Symbol/keyFor/cross-realm.js built-ins/Symbol/keyFor/cross-realm.js - + One realm. - + built-ins/Array/prototype/reduceRight/length-near-integer-limit.js built-ins/String/prototype/localeCompare/15.5.4.9_CE.js built-ins/JSON/stringify/replacer-function-object-deleted-property.js - + To be investigated. built-ins/Function/prototype/toString/method-computed-property-name.js Invalid test. - + ### Skipped cases `xst` skips cases with the following features: diff --git a/documentation/xs/XS Differences.md b/documentation/xs/XS Differences.md index 6e9a39a878..85daa7024e 100644 --- a/documentation/xs/XS Differences.md +++ b/documentation/xs/XS Differences.md @@ -5,18 +5,18 @@ Revised: October 10, 2018 ## Ultra-light JavaScript XS is the JavaScript engine at the core of Moddable applications and tools. XS has existed since the beginning of this century. You can get the latest version on [GitHub](https://github.com/Moddable-OpenSource/moddable). -Other JavaScript engines are primarily used for client or server side web development. Their main focus is speed, their main cost is the significant resources they consume to get that speed. +Other JavaScript engines are primarily used for client or server side web development. Their main focus is speed, their main cost is the significant resources they consume to get that speed. The XS engine targets embedded platforms built around microcontrollers like the [ESP8266](https://www.espressif.com/en/products/hardware/esp8266ex/overview) or [ESP32](https://www.espressif.com/en/products/hardware/esp32/overview). XS also runs on the usual desktop and mobile platforms. The challenges of embedded development are well known: limited memory and limited performance. Compared to hardware that usually runs JavaScript for the web on the client or the server sides, the differences are measured in orders of magnitude, not percentages. Moreover battery life is often critical. -Despite such constraints, and unlike other scripting libraries available on microcontrollers, XS always strives to fully implement the quite extensive [ECMAScript Language Specification](https://tc39.github.io/ecma262/). +Despite such constraints, and unlike other scripting libraries available on microcontrollers, XS always strives to fully implement the quite extensive [ECMAScript Language Specification](https://tc39.github.io/ecma262/). These constraints have consequences. This document highlights key differences between XS, with its focus on embedded devices, and JavaScript engines focused on web development. ## Spare runtime resources -Embedded platforms do not exist alone. You need a computer to develop applications for them. Therefore, you should prepare in advance of execution, at *compile* time, everything you can in order to spare *run*-time resources. +Embedded platforms do not exist alone. You need a computer to develop applications for them. Therefore, you should prepare in advance of execution, at *compile* time, everything you can in order to spare *run*-time resources. On the web, JavaScript engines currently execute scripts and modules from their source code. For microcontrollers, the XS compiler transforms modules source code into byte code on your computer, so the XS engine on the microcontroller only has to execute byte code. @@ -27,12 +27,12 @@ At Moddable, we generalized this approach beyond scripts to all kinds of assets. Despite being based on JavaScript, embedded development with XS is more similar to mobile development than web development. Applications built with XS are described by a manifest and built with a tool chain that includes the XS compiler and linker, asset encoders, C compiler and linker, a debugger, and ROM flasher. ## Prepare the environment -On embedded platforms, the amount of RAM is extremely small, often under 64 KB. The amount of ROM is larger, 512 KB to 4 MB, roughly the same amount of data downloaded for a typical modern web page. An application's native code and data are flashed into ROM. +On embedded platforms, the amount of RAM is extremely small, often under 64 KB. The amount of ROM is larger, 512 KB to 4 MB, roughly the same amount of data downloaded for a typical modern web page. An application's native code and data are flashed into ROM. JavaScript modules compiled to byte code and encoded assets are stored in flash ROM as part of the native data. This allows the byte code and assets to be used in place, rather than being copied to RAM first. For example, the XS engine executes byte code directly from ROM. Still, a significant amount of RAM is needed for the JavaScript environment your application runs in. For example: -- JavaScript Built-ins including `Object`, `Function`, `Boolean`, `Symbol`, `Error`, `Number`, `Math`, `Date`, `String`, `RegExp`, `Array`, `TypedArray`, `Map`, `Set`, `WeakMap`, `WeakSet`, `ArrayBuffer`, `SharedArrayBuffer`, `DataView`, `Atomics`, `JSON`, `Generator`, `AsyncGenerator`, `AsyncFunction`, `Promise`, `Reflect`, `Proxy`, etc. -- Modules your application uses to do something useful, like a user interface framework, a secure network framework, etc. +- JavaScript Built-ins including `Object`, `Function`, `Boolean`, `Symbol`, `Error`, `Number`, `Math`, `Date`, `String`, `RegExp`, `Array`, `TypedArray`, `Map`, `Set`, `WeakMap`, `WeakSet`, `ArrayBuffer`, `SharedArrayBuffer`, `DataView`, `Atomics`, `JSON`, `Generator`, `AsyncGenerator`, `AsyncFunction`, `Promise`, `Reflect`, `Proxy`, etc. +- Modules your application uses to do something useful, like a user interface framework, a secure network framework, etc. Constructing built-ins and loading modules creates many classes, functions, and prototype objects. These objects often require more RAM than is present on a modest microcontroller. @@ -41,7 +41,7 @@ To solve this problem, the XS linker allows you to prepare a JavaScript environm The benefits are significant: - Since almost nothing is ever copied from ROM to RAM, your application runs with a small amount of RAM. -- Since everything is ready in ROM, your application boots instantaneously. +- Since everything is ready in ROM, your application boots instantaneously. > The XS linker cannot preload a module with a body that calls a native function that is only available on the microcontroller. Typically there will be only one module like that to start your application. @@ -50,9 +50,9 @@ But what happens when applications want to modify objects that the XS linker pre The XS engine maintains a a table of aliases which is initially empty. All aliasable objects in ROM have an index in that table. When an application modifies an aliasable object, the aliasable object is cloned into RAM and inserted into the table to override the aliasable object. -Such a mechanism has a cost in memory footprint and performance, but is essential for conformance with the JavaScript language specification. However JavaScript has a feature to specify that an object cannot be modified: `Object.freeze`. When objects are frozen, the XS linker does not index them as aliasable. +Such a mechanism has a cost in memory footprint and performance, but is essential for conformance with the JavaScript language specification. However JavaScript has a feature to specify that an object cannot be modified: `Object.freeze`. When objects are frozen, the XS linker does not index them as aliasable. -Modules can use `Object.freeze` in their body to tell the XS linker which objects do not need to be indexed as aliasable. Calling that for each object is tedious enough, so the XS linker can automatically freeze all class, function and prototype objects, as well as other built-in objects like `Atomics`, `JSON`, `Math` and `Reflect`. +Modules can use `Object.freeze` in their body to tell the XS linker which objects do not need to be indexed as aliasable. Calling that for each object is tedious enough, so the XS linker can automatically freeze all class, function and prototype objects, as well as other built-in objects like `Atomics`, `JSON`, `Math` and `Reflect`. In ECMAScript parlance, that is related to a [frozen realm](https://github.com/tc39/proposal-frozen-realms). @@ -63,7 +63,7 @@ As mentioned above, JavaScript defines many of built-ins, which are all implemen Based on the byte code of your modules, the XS linker can strip unused native code from the XS engine itself. So your application will run its own version of the XS engine, tailored to reduce its ROM footprint. -That is automatic for applications that are self-contained and updated as a whole, which is still common on embedded platforms for the sake of consistency, safety, and security. +That is automatic for applications that are self-contained and updated as a whole, which is still common on embedded platforms for the sake of consistency, safety, and security. For applications that expect to be customized or updated with separate modules, you can manually specify the built-in features to strip from the XS engine and to document the profiled JavaScript environment. For instance you can strip `eval`, `Function`, etc to get rid of the XS parser and byte coder. @@ -77,7 +77,7 @@ Web development often claims to be "pure" Javascript while it is in fact relying At Moddable, we use native code only when necessary, for instance to build drivers, or when the memory footprint or performance gains are obvious, for instance in our graphics library and user interface framework. -Indeed a reasonable solution to sparing resources is to sometimes use native code instead of JavaScript. Remember that your application is in charge of everything. +Indeed a reasonable solution to sparing resources is to sometimes use native code instead of JavaScript. Remember that your application is in charge of everything. > Since the tool chain always requires compiling and linking native code, there is no overhead in your development cycle. diff --git a/documentation/xs/XS Marshalling.md b/documentation/xs/XS Marshalling.md index 7b89ef955d..cfbeff12d2 100644 --- a/documentation/xs/XS Marshalling.md +++ b/documentation/xs/XS Marshalling.md @@ -4,13 +4,13 @@ Revised: March 15, 2021 ## Introduction -To exchange data between machines that can run in separate threads, XS always supported marshalling thru the **XS in C** programming interface. +To exchange data between machines that can run in separate threads, XS always supported marshalling thru the **XS in C** programming interface. Even if you do not write C code, this document is useful if you write JavaScript code using the standard `Worker` programming interface provided by the [worker](../base/worker.md) module of the Moddable SDK. ## What Is Marshalling? -Similar to what `JSON.stringify` and `JSON.parse` do with a string, *marshalling* creates a memory block from a JavaScript value and *demarshalling* creates a JavaScript value from a memory block. The format of the memory block is binary. +Similar to what `JSON.stringify` and `JSON.parse` do with a string, *marshalling* creates a memory block from a JavaScript value and *demarshalling* creates a JavaScript value from a memory block. The format of the memory block is binary. XS machines can be created from scratch or cloned from a read-only machine. Typically on micro-controllers, multiple small machines can be created in RAM based based on one large read-only machine in ROM. @@ -34,10 +34,10 @@ When two machines are cloned from the same read-ony machinee, marshalling can ta What can be exchanged between alien machines? -Firstly, everything that can be exchanged thru JSON: +Firstly, everything that can be exchanged thru JSON: - `false` -- `null` +- `null` - `true` - numbers - strings @@ -49,9 +49,9 @@ Firstly, everything that can be exchanged thru JSON: XS can also marshall other values not possible using JSON: -- `undefined` +- `undefined` - bigints -- instances of +- instances of - `Boolean`, `Error`, `EvalError`, `RangeError`, `ReferenceError`, `SyntaxError`, `TypeError`, `URIError`, `AggregateError` - `Number`, `Date` - `String`, `RegExp` @@ -87,7 +87,7 @@ In these cases, XS tries to report a meaningful error: catch { } -breaks into **xsbug** with +breaks into **xsbug** with main.js (2) # Break: (host): marshall [0].p.x: accessor! @@ -110,7 +110,7 @@ Like what happens with `JSON.stringify` and `JSON.parse`, custom prototypes are const o = new C(); trace(`${o.constructor.name}\n`); // C worker.postMessage(o); - + ##### worker.js self.onmessage = function(m) { trace(`${m.constructor.name}\n`); // Object @@ -126,7 +126,7 @@ But if custom prototypes are in the read-only machine, they are kept: const o = new C(); trace(`${o.constructor.name}\n`); // C worker.postMessage(o); - + ##### worker.js self.onmessage = function(m) { trace(`${m.constructor.name}\n`); // C @@ -135,7 +135,7 @@ But if custom prototypes are in the read-only machine, they are kept: ### Private Fields Similarly, private fields are ignored when marshalled. - + ##### main.js class C { #x; @@ -148,7 +148,7 @@ Similarly, private fields are ignored when marshalled. } const o = new C("oops"); worker.postMessage(o); - + ##### worker.js self.onmessage = function(m) { trace(`${m.toString()}\n`); // [object Object] @@ -166,12 +166,12 @@ Except when the class is in the read-only machine: return this.#x; } } - + ##### main.js import { C } from "preload"; const o = new C("wow"); worker.postMessage(o); - + ##### worker.js self.onmessage = function(m) { trace(`${m.toString()}\n`); // wow @@ -187,7 +187,7 @@ References to instances in the read-only machine are preserved: ##### main.js import { o } from "preload"; worker.postMessage({ o }); - + ##### worker.js import { o } from "preload"; self.onmessage = function(m) { @@ -205,7 +205,7 @@ That is especially useful for exchanging references to objects with methods, lik return Reflect.get(...arguments); } }); - + ##### main.js const target = { message1: "hello", @@ -213,7 +213,7 @@ That is especially useful for exchanging references to objects with methods, lik }; import { handler } from "preload"; worker.postMessage(new Proxy(target, handler)); - + ##### worker.js self.onmessage = function(m) { trace(`${m.message1}\n`); // hello @@ -231,7 +231,7 @@ Like private fields, properties keyed by symbols are ignored when marshalled, ex import { s } from "preload"; const o = { [s]: "wow" }; worker.postMessage(o); - + ##### worker.js import { s } from "preload"; self.onmessage = function(m) { diff --git a/documentation/xs/XS Platforms.md b/documentation/xs/XS Platforms.md index 8ff9de9ea6..f4c64e1ce4 100644 --- a/documentation/xs/XS Platforms.md +++ b/documentation/xs/XS Platforms.md @@ -8,11 +8,11 @@ A platform is a combination of hardware and system software. For each platform, Historically, XS used one interface file, `xsPlatform.h` splitting the implementation into two files: `xsPlatform.c` and `xsHost.c`. Many platforms shared the same interface and implementation files, based either on the KinomaJS platform abstraction, or on an adhoc platform abstraction for command line tools. -Further, an XS machine had many ways to find and load modules and programs: from JS files, from stand alone compiled XSB files with or without companion DLL or SO files, and from a linked XSA file with a companion DLL or SO file... The XS platform was in charge of providing such options. +Further, an XS machine had many ways to find and load modules and programs: from JS files, from stand alone compiled XSB files with or without companion DLL or SO files, and from a linked XSA file with a companion DLL or SO file... The XS platform was in charge of providing such options. When we started working on microcontrollers, the main inspiration for XS platforms was the adhoc platform abstraction for command line tools, which was the most complex version. -Today the XS runtime has been significantly streamlined, especially on microcontrollers. XS machines are always cloned from a read-only machine prepared by the XS linker. There are only modules, byte coded by the XS compiler. Modules are either preloaded or prepared to be loaded and unloaded at runtime. +Today the XS runtime has been significantly streamlined, especially on microcontrollers. XS machines are always cloned from a read-only machine prepared by the XS linker. There are only modules, byte coded by the XS compiler. Modules are either preloaded or prepared to be loaded and unloaded at runtime. Consequently, it is now much simpler to build an XS platform. This document describes the necessary interface and implementation files. @@ -42,7 +42,7 @@ XS mostly relies on constants and functions from the C stantard library, accesse #define c_free free #define c_malloc malloc //... - + Such definitions, and the corresponding includes, are the most significant part of the interface file. The macros allows a platform to provide its own constants and functions. See any of the provided `xsPlatform.h` for the list of macros to define. ### ESP macros @@ -52,7 +52,7 @@ The Xtensa instruction set and architecture, used most notably in microcontrolle #define c_read8(POINTER) *((txU1 *)(POINTER)) #define c_read16(POINTER) *((txU2 *)(POINTER)) #define c_read32(POINTER) *((txU4 *)(POINTER)) - + #define ICACHE_FLASH_ATTR #define ICACHE_RODATA_ATTR #define ICACHE_XS6RO_ATTR @@ -87,7 +87,7 @@ On Windows, the `mxMachinePlatform` macro adds the socket and message window han The implementation file first includes `xsAll.h`, which contains the definitions of all XS macros and types, and the declarations of all XS extern functions. Then the platform has to implement the functions described here under. -XS machines do not support multiple threads, though platforms can support multiple threads, each with their own XS machines. All calls and callbacks described here must happen in the thread that created or cloned the machine. +XS machines do not support multiple threads, though platforms can support multiple threads, each with their own XS machines. All calls and callbacks described here must happen in the thread that created or cloned the machine. The functions are grouped into meaningful sections. The xsPlatform.c file can also provide POSIX functions that the platform is missing. @@ -112,7 +112,7 @@ The functions in this section are only necessary for the debug version of XS. Th #ifdef mxDebug // debug functions #endif - + If the platform does not support the communication with **xsbug**, functions in this section can be empty, except `fxIsConnected` and `fxIsReadable`, which must return `0`. Communication between **xsbug** and the XS machine can be done over either a TCP/IP or serial connection. In the case of a TCP/IP connection, **xsbug** is the server and XS machines are clients. When using a serial connection, **xsbug** continues to communication over TCP/IP and a bridge running on the computer relays data between the serial and TCP connections. In the case of the ESP8266, this relay is performed by **serial2xsbug**. @@ -150,7 +150,7 @@ On Windows the platform uses `WSAAsyncSelect` with the `WM_XSBUG` message: - `void fxConnect(txMachine* the)` -XS calls `fxConnect` to connect `the` machine to **xsbug**. +XS calls `fxConnect` to connect `the` machine to **xsbug**. For TCP/IP connections, platforms create a socket and connect it to **xsbug**. On Mac and Windows the address of **xsbug** is usually `localhost`, on other platforms it is usually defined by an environment variable. The port of **xsbug** defaults to `5002` by convention. @@ -160,7 +160,7 @@ Machines are connect to **xsbug** after being created, i.e. `fxConnect` happens - `void fxDisconnect(txMachine* the)` -XS calls `fxDisconnect` to disconnect `the` machine from **xsbug**. +XS calls `fxDisconnect` to disconnect `the` machine from **xsbug**. For TCP/IP connections, platforms close the socket. @@ -176,7 +176,7 @@ XS calls `fxIsConnected` to know if `the` machine is connected to **xsbug**. - `txBoolean fxIsReadable(txMachine* the)` -XS calls `fxIsReadable` to know if `the` machine received a message from **xsbug**. Platforms must return 1 or 0 depending on the availability of bytes to read. +XS calls `fxIsReadable` to know if `the` machine received a message from **xsbug**. Platforms must return 1 or 0 depending on the availability of bytes to read. The performance of the implementation of `fxIsReadable` is important since XS calls `fxIsReadable` at every `LINE` byte code (e.g. for each line of JavaScript source code executed). @@ -184,7 +184,7 @@ The performance of the implementation of `fxIsReadable` is important since XS ca - `void fxReceive(txMachine* the)` -XS calls `fxReceive` to receive a message from **xsbug**. The implementation reads bytes into `the->debugBuffer` and sets `the->debugOffset` to the number of bytes received. +XS calls `fxReceive` to receive a message from **xsbug**. The implementation reads bytes into `the->debugBuffer` and sets `the->debugOffset` to the number of bytes received. XS calls `fxReceive` repeatedly until the entire message is received. The maximum number of bytes that can be read by `fxReceive` is `sizeof(the->debugBuffer) - 1`. @@ -192,15 +192,15 @@ XS calls `fxReceive` repeatedly until the entire message is received. The maximu - `void fxSend(txMachine* the, txBoolean more)` -XS calls `fxSend` to send a message to **xsbug**. The implementation gets the number of bytes to send from `the->echoOffset` and write bytes from `the->echoBuffer`. +XS calls `fxSend` to send a message to **xsbug**. The implementation gets the number of bytes to send from `the->echoOffset` and write bytes from `the->echoBuffer`. -XS calls `fxSend ` repeatedly until the entire message is sent, `more` equals `1` while the message is incomplete, `0` when the message is complete. +XS calls `fxSend ` repeatedly until the entire message is sent, `more` equals `1` while the message is incomplete, `0` when the message is complete. -- ### Eval -The standard `eval` function, `Function` constructor and `Generator` constructor must transform source code into byte codes and keys. +The standard `eval` function, `Function` constructor and `Generator` constructor must transform source code into byte codes and keys. XS lets the platform decides is such feature is worth the memory it takes. @@ -248,7 +248,7 @@ Keys are the names and symbols that XS uses to identify properties. `fxBuildKeys` is called only when creating an XS machine, in order to initialize the default keys used by the standard ECMAScript host functions. -On most platforms today, XS machines are cloned. The default keys are available and ready to be used in the read-only machine. So `fxBuildKeys` is never called and can be empty. +On most platforms today, XS machines are cloned. The default keys are available and ready to be used in the read-only machine. So `fxBuildKeys` is never called and can be empty. If the platform supports the creation of XS machines from scratch, `fxBuildKeys` must be implemented as: @@ -271,7 +271,7 @@ If the platform supports the creation of XS machines from scratch, `fxBuildKeys` ### Memory -XS machines use two heaps: the chunks heap and the slots heap. +XS machines use two heaps: the chunks heap and the slots heap. Chunks are blocks of variable size that the garbage collector can move to compact memory. XS stores strings, buffers, arrays, etc into chunks. On microcontrollers without a dedicated memory management unit, chunks are also useful to store any kind of data. For instance Piu uses chunks to store its containment hierarchy. @@ -325,15 +325,15 @@ On platforms that support several ways to get modules, the implementation of `fx - `txID fxFindModule(txMachine* the, txID moduleID, txSlot* slot)` -XS calls `fxFindModule` to find an imported or required module. +XS calls `fxFindModule` to find an imported or required module. The `moduleID` argument is the importing or requiring module identifier. It is `XS_NO_ID` when the machine itself requires a module. -The `slot` argument is the imported or required module name. It is the module specifier of the `import` syntactical construct or the module parameter of the `require` host function. +The `slot` argument is the imported or required module name. It is the module specifier of the `import` syntactical construct or the module parameter of the `require` host function. If the module is found, `fxFindModule` returns the module identifier, otherwise `fxFindModule` returns `XS_NO_ID`. -A module identifier is a unique `txID`, but the platform defines the format of its corresponding key: it can be a path, a URL, a URI... +A module identifier is a unique `txID`, but the platform defines the format of its corresponding key: it can be a path, a URL, a URI... The platform defines also how the importing or requiring module identifier and the imported or required module name are merged. The usual convention is based on absolute (`/*`), relative (`./*`, `../*`) or search (*) paths. @@ -349,15 +349,15 @@ Finding modules can involve looking for various kinds of files, using a set of p txSlot *key; txString slash; txID id; - + fxToStringBuffer(the, slot, name, sizeof(name)); if (!c_strncmp(name, "/", 1)) { absolute = 1; - } + } else if (!c_strncmp(name, "./", 2)) { dot = 1; relative = 1; - } + } else if (!c_strncmp(name, "../", 3)) { dot = 2; relative = 1; @@ -401,7 +401,7 @@ Finding modules can involve looking for various kinds of files, using a set of p } return XS_NO_ID; } - + txBoolean fxFindScript(txMachine* the, txString path, txID* id) { txPreparation* preparation = the->archive; @@ -436,7 +436,7 @@ Preparing modules can involve reading and mapping files, parsing, scoping and by txScript* script = fxLoadScript(the, path); fxResolveModule(the, moduleID, script, C_NULL, C_NULL); } - + txScript* fxLoadScript(txMachine* the, txString path) { txPreparation* preparation = the->archive; @@ -460,7 +460,7 @@ Promises are essentially asynchronous. The `then` method of a `Promise` object t > *A Job is an abstract operation that initiates an ECMAScript computation when no other ECMAScript computation is currently in progress.* (ECMAScript® 2015 Language Specification, Section 8.4). -XS takes care queuing and running Jobs but relies on platforms for their scheduling. +XS takes care queuing and running Jobs but relies on platforms for their scheduling. -- @@ -475,7 +475,7 @@ For instance on Mac the platform uses a run loop source and `CFRunLoopSourceSign txMachine* the = info; fxRunPromiseJobs(the); } - + void fxQueuePromiseJobs(txMachine* the) { CFRunLoopSourceSignal(the->promiseSource); @@ -495,7 +495,7 @@ On Windows the platform uses a message window and `PostMessage`: } return 0; } - + void fxQueuePromiseJobs(txMachine* the) { PostMessage(the->window, WM_PROMISE, 0, 0); @@ -529,7 +529,7 @@ Applications that use `Atomics.wait` and `Atomics.wake` must call `xsTerminateSh void* fxCreateSharedChunk(txInteger byteLength); -`fxCreateSharedChunk` allocates a shared chunk, `byteLength` is the size of its data, which must be initialised to zero. +`fxCreateSharedChunk` allocates a shared chunk, `byteLength` is the size of its data, which must be initialised to zero. Typically platforms use a reference count to track how many machines are referencing the shared chunk. `fxCreateSharedChunk` must initialise the reference count to one. @@ -537,7 +537,7 @@ Typically platforms use a reference count to track how many machines are referen void fxLockSharedChunk(void* data); -`fxLockSharedChunk` locks the shared chunk, `data` is a pointer to the data of the shared chunk. +`fxLockSharedChunk` locks the shared chunk, `data` is a pointer to the data of the shared chunk. `fxLockSharedChunk` is never called if the platform supports GCC atomics. @@ -551,7 +551,7 @@ Machines call `fxReleaseSharedChunk` when they do not reference the shared chunk Typically platforms use an atomic operation to decrement the reference count of the shared chunk and free the shared chunk when the reference count is zero. -`fxReleaseSharedChunk` is the destructor of the host slot. +`fxReleaseSharedChunk` is the destructor of the host slot. void* fxRetainSharedChunk(void* data); @@ -561,7 +561,7 @@ Typically platforms use an atomic operation to increment the reference count of void fxUnlockSharedChunk(void* data); -`fxUnlockSharedChunk` unlocks the shared chunk. `data` is a pointer to the data of the shared chunk. +`fxUnlockSharedChunk` unlocks the shared chunk. `data` is a pointer to the data of the shared chunk. `fxUnlockSharedChunk` is never called if the platform supports GCC atomics. @@ -569,11 +569,11 @@ Typically platforms use an atomic operation to increment the reference count of If the application did not call `fxInitializeSharedCluster` or if the current thread is the thread that called `fxInitializeSharedCluster`, `fxWaitSharedChunk` throws a `TypeError` object. -If the 32-bit signed integer at `byteOffset` in `data` is not equal to `value`, `fxWaitSharedChunk` returns `-1` immediately. Else `fxWaitSharedChunk` suspends the current thread. +If the 32-bit signed integer at `byteOffset` in `data` is not equal to `value`, `fxWaitSharedChunk` returns `-1` immediately. Else `fxWaitSharedChunk` suspends the current thread. If a matching call to `fxWakeSharedChunk` resumed the thread, `fxWaitSharedChunk` returns `1`. A matching call is a call with the same `data` and `byteOffset`. -If `timeout` expired, `fxWaitSharedChunk` returns `0`. `timeout` is a number between `Date.now()` and `C_INFINITY`. +If `timeout` expired, `fxWaitSharedChunk` returns `0`. `timeout` is a number between `Date.now()` and `C_INFINITY`. txInteger fxWakeSharedChunk(txMachine* the, void* data, txInteger byteOffset, txInteger count); diff --git a/documentation/xs/XS Profiler.md b/documentation/xs/XS Profiler.md index 4786ae16f4..7a0f3bff08 100644 --- a/documentation/xs/XS Profiler.md +++ b/documentation/xs/XS Profiler.md @@ -5,13 +5,13 @@ The XS profiler is a sample based JavaScript profiler. The XS profiler also repo There are two implementations of the profiler: -- **Instrument**: XS sends profile records and samples to **xsbug**. The instrument profiler is used by Moddable SDK applications in the simulator and on devices. +- **Instrument**: XS sends profile records and samples to **xsbug**. The instrument profiler is used by Moddable SDK applications in the simulator and on devices. > Build XS with `mxInstrument` defined. -- **File**: XS accumulates profile records and samples in RAM then saves them into a [`.cpuprofile`](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-Profile) file. The file profiler is used by command line tools including **xst** and **xsnap**. +- **File**: XS accumulates profile records and samples in RAM then saves them into a [`.cpuprofile`](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-Profile) file. The file profiler is used by command line tools including **xst** and **xsnap**. -> Build XS with `mxProfile` defined and xsProfile.c included. +> Build XS with `mxProfile` defined and xsProfile.c included. Both profilers require debugging information, so scripts must be built with debugging enabled. The instrument profiler requires a connection to **xsbug**. Therefore, profiling is only supported in builds of XS with debugging support enabled. @@ -33,7 +33,7 @@ for (let i = 0; i < 10; i++) { ``` For function instances, the profile ID is stored in the ID of the internal home slot. For function primitives, the profile ID is stored in the slot itself. This approach means that profile IDs require no additional RAM or storage space. All debug builds are ready to be profiled. - + The profile ID of the host is 0. The profile ID of the garbage collector is 1. For newly created machines, function profile IDs start incrementing from 2; for cloned machines, from the profile ID stored in the preparation. ### Record @@ -47,7 +47,7 @@ A profile record is created for each function observed to run during a profile s Profile records are only stored once by the file profiler and only sent once to **xsbug** by the instrument profiler. -The home slot allows function identifiers to be more detailed for function instances (`Array.prototype.push`) than for function primitives (`push`). +The home slot allows function identifiers to be more detailed for function instances (`Array.prototype.push`) than for function primitives (`push`). ### Sample @@ -56,7 +56,7 @@ A profile sample is created for each sample taken during a profile session. The - Time delta: microseconds since the last sample. - Profile ID stack: sequence of profile ID in stack order. The first profile ID is the function hit by the profiler. The last profile ID is always the host (0). -For each sample, The instrument profiler simply sends the sample to **xsbug**, which updates the call graph and the durations of the profile records. The file profiler updates the call graph and stores the time delta and the first profile ID. +For each sample, The instrument profiler simply sends the sample to **xsbug**, which updates the call graph and the durations of the profile records. The file profiler updates the call graph and stores the time delta and the first profile ID. ### Time @@ -78,12 +78,12 @@ Both the instrument and file profilers allocate their buffers outside the XS hea The instrument profiler uses: -- A bitmap to remember which profile records have already been sent to **xsbug**, i.e. one bit for each profile ID. +- A bitmap to remember which profile records have already been sent to **xsbug**, i.e. one bit for each profile ID. - Buffers for profile samples. The size of the buffers is the size of the XS stack divided by the size of a frame and multiplied by the size of a profile ID. ### File Profiler -The file profiler uses growing buffers to store profile records and samples. +The file profiler uses growing buffers to store profile records and samples. ## How To Use @@ -109,7 +109,7 @@ Use the `xsStartProfiling` and `xsStopProfiling` macros to start and stop the pr Because you can open the `.cpuprofile` file created by the File Profiler with at least three different applications, you get somewhat different views of the same data. -In the three viewers, the first column is the "Self Time", the second column is the "Total Time". +In the three viewers, the first column is the "Self Time", the second column is the "Total Time". Google Chrome DevTools and xsbug can toggle between a "Bottom Up" viewer (from callees to callers) and a "Top Down" viewer (from callers to callees). diff --git a/documentation/xs/XS in C.md b/documentation/xs/XS in C.md index c2e2f8bb75..36b61a8f6c 100644 --- a/documentation/xs/XS in C.md +++ b/documentation/xs/XS in C.md @@ -2,22 +2,22 @@ | Copyright (c) 2016-2023 Moddable Tech, Inc. | | This file is part of the Moddable SDK Runtime. - | + | | The Moddable SDK Runtime is free software: you can redistribute it and/or modify | it under the terms of the GNU Lesser General Public License as published by | the Free Software Foundation, either version 3 of the License, or | (at your option) any later version. - | + | | The Moddable SDK Runtime is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU Lesser General Public License for more details. - | + | | You should have received a copy of the GNU Lesser General Public License | along with the Moddable SDK Runtime. If not, see . | - | This file incorporates work covered by the following copyright and - | permission notice: + | This file incorporates work covered by the following copyright and + | permission notice: | | Copyright (C) 2010-2016 Marvell International Ltd. | Copyright (C) 2002-2010 Kinoma, Inc. @@ -42,16 +42,16 @@ Revised: June 11, 2023 ## About This Document -This document describes XS in C, the C interface to the runtime of the XS JavaScript engine. Information on building XS for target software/hardware platforms is provided in the companion document [XS Platforms.md](./XS%20Platforms.md). +This document describes XS in C, the C interface to the runtime of the XS JavaScript engine. Information on building XS for target software/hardware platforms is provided in the companion document [XS Platforms.md](./XS%20Platforms.md). -In accordance with the ECMAScript specifications, the XS runtime implements only generic features that all scripts can use. An application defines the specific features that its own scripts can use through C callbacks. An application that uses the XS runtime is a host in ECMAScript terminology. +In accordance with the ECMAScript specifications, the XS runtime implements only generic features that all scripts can use. An application defines the specific features that its own scripts can use through C callbacks. An application that uses the XS runtime is a host in ECMAScript terminology. XS in C provides macros to access properties of objects. XS provides two functionally equivalent variations of many of the macros. The macros prefixed with `xs` alone are somewhat more convenient to work with but generate larger binary code whereas the macros prefixed with `xsmc` generate smaller binary code at the expense of being more difficult to use. To use the `xsmc*` macros include "xsmc.h" and do not include "xs.h". to use the macros prefixed with `xs` alone, include "xs.h" and do not include "xsmc.h". Including the `xsmc.h` header file makes the `xs` versions of some operations available. ## Table of Contents * [Slots](#slots): Describes how to handle ECMAScript constructs in C callbacks, with examples that show the correspondences between ECMAScript and XS in C. - * [Slot types](#slot-types) + * [Slot types](#slot-types) * [Primitives](#primitives) * [ArrayBuffer](#arraybuffer) * [Instances and Prototypes](#instances-and-prototypes) @@ -99,7 +99,7 @@ enum { xsSymbolType, xsBigIntType, xsBigIntXType, - xsReferenceType + xsReferenceType } typedef char xsType; ``` @@ -149,8 +149,8 @@ Returns the type of the slot switch(typeof arguments[0]) { case "undefined": break; /* Null is an object. */ - case "boolean": break; - /* Integers are numbers */ + case "boolean": break; + /* Integers are numbers */ case "number": break; /* StringX is a string */ case "string": break; @@ -159,7 +159,7 @@ switch(typeof arguments[0]) { case "bigint": break; case "object": break; case "function": break; -} +} ``` ##### In C: @@ -175,7 +175,7 @@ switch(xsTypeOf(xsArg(0))) { case xsSymbolType: break; case xsBigIntType: break; case xsReferenceType: break; /* Objects and functions are references. */ -} +} ``` @@ -223,10 +223,10 @@ Sets the specified slot value to `null` These slots contain values of the corresponding type. - typedef char xsBooleanValue; - typedef long xsIntegerValue; - typedef double xsNumberValue; - + typedef char xsBooleanValue; + typedef long xsIntegerValue; + typedef double xsNumberValue; + The following macros return slots of each of these types (set to a particular value) or access/set the value in a slot. When accessing the value in a slot, you specify a desired type; the slot is coerced to the requested type if necessary, and the value is returned. **`xsSlot xsTrue`** @@ -375,7 +375,7 @@ A string value is a pointer to a UTF-8 C string. The XS runtime virtual machine Returns a string slot -C constants, C globals, or C locals can safely be passed to the `xsString` macro, since it duplicates its parameter. +C constants, C globals, or C locals can safely be passed to the `xsString` macro, since it duplicates its parameter. *** @@ -412,7 +412,7 @@ Sets the slot value to a string | `theBuffer` | A buffer to copy the string into | `theSize` | The size of the buffer -Copies the string value and returns the buffer containing the copy of the string. The buffer provided has to be large enough to hold a copy of the string value. +Copies the string value and returns the buffer containing the copy of the string. The buffer provided has to be large enough to hold a copy of the string value. *** @@ -442,26 +442,26 @@ Copies the string into an allocated buffer and sets the slot value to the string ### ArrayBuffer -In ECMAScript an `ArrayBuffer` is commonly used to store fixed length binary data. +In ECMAScript an `ArrayBuffer` is commonly used to store fixed length binary data. #### Macros **`xsSlot xsArrayBuffer(void *theData, xsIntegerValue theSize)`** **`void xsmcSetArrayBuffer(xsSlot theSlot, void *theData, xsIntegerValue theSize)`** - + | Arguments | Description | | --- | :-- | | `theData` | A pointer to the data to copy into the `ArrayBuffer`, or `NULL` to leave the `ArrayBuffer` data uninitialized | `theSize` | The size of the data in bytes -Creates an `ArrayBuffer` instance and returns a reference to the new `ArrayBuffer` instance +Creates an `ArrayBuffer` instance and returns a reference to the new `ArrayBuffer` instance *** **`void xsGetArrayBufferData(xsSlot theSlot, xsIntegerValue theOffset, void *theData, xsIntegerValue theSize)`**
**`void xsmcGetArrayBufferData(xsSlot theSlot, xsIntegerValue theOffset, void *theData, xsIntegerValue theSize)`** - + | Arguments | Description | | --- | :-- | | `theSlot` | The `ArrayBuffer` slot @@ -475,7 +475,7 @@ Copies bytes from the `ArrayBuffer` **`void xsSetArrayBufferData(xsSlot theSlot, xsIntegerValue theOffset, void *theData, xsIntegerValue theSize)`**
**`void xsmcSetArrayBufferData(xsSlot theSlot, xsIntegerValue theOffset, void *theData, xsIntegerValue theSize)`** - + | Arguments | Description | | --- | :-- | | `theSlot` | The `ArrayBuffer` slot @@ -511,7 +511,7 @@ Returns the size of the `ArrayBuffer` in bytes *** **`void xsSetArrayBufferLength(xsSlot theSlot, xsIntegerValue theSize)`** - + | Arguments | Description | | --- | :-- | | `theSlot` | The `ArrayBuffer` slot @@ -523,14 +523,14 @@ Sets the length of the `ArrayBuffer` **`void *xsToArrayBuffer(xsSlot theSlot)`**
**`void *xsmcToArrayBuffer(xsSlot theSlot)`** - + | Arguments | Description | | --- | :-- | | `theSlot` | The `ArrayBuffer` slot Returns a pointer to the `ArrayBuffer` data -For speed, the `xsToArrayBuffer ` macro returns the value contained in the slot itself, a pointer to the buffer in the memory managed by XS. Since the XS runtime can compact memory containing string values, the result of the `xsToArrayBuffer ` macro cannot be used across or in other macros of XS in C. +For speed, the `xsToArrayBuffer ` macro returns the value contained in the slot itself, a pointer to the buffer in the memory managed by XS. Since the XS runtime can compact memory containing string values, the result of the `xsToArrayBuffer ` macro cannot be used across or in other macros of XS in C. *** @@ -581,7 +581,7 @@ Returns a reference to the prototype instance created by the XS runtime. | --- | :-- | | `theLength` | The array length property to set -Creates an array instance, and returns a reference to the new array instance +Creates an array instance, and returns a reference to the new array instance ##### In ECMAScript: @@ -600,7 +600,7 @@ xsNewArray(5); **`xsSlot xsNewObject()`**
**`xsSlot xsmcNewObject()`** -Creates an object instance, and returns a reference to the new object instance +Creates an object instance, and returns a reference to the new object instance ##### In ECMAScript: @@ -620,7 +620,7 @@ xsNewObject(); | Arguments | Description | | --- | :-- | -| `theSlot` | The result slot +| `theSlot` | The result slot The `xsmcSetNewObject` macro is functionally equivalent to the `xsNewObject` macro. The property is returned in the slot provided. @@ -670,7 +670,7 @@ if (xsIsInstanceOf(xsThis, xsObjectPrototype)) ### Keys, Identifiers and Indexes -In ECMAScript, the properties of an object are identified by number, string or symbol values – a.k.a. the property **key**. In XS in C you can access properties with property keys through the `xsGetAt`, `xsSetAt`, etc macros described below. +In ECMAScript, the properties of an object are identified by number, string or symbol values – a.k.a. the property **key**. In XS in C you can access properties with property keys through the `xsGetAt`, `xsSetAt`, etc macros described below. If the number or string value of a property key can be converted into a 32-bit unsigned integer, XS uses the result of the conversion – a.k.a. the property **index** — to identify the property. In XS in C, you can access properties directy with property indexes through the `xsGetIndex`, `xsSetIndex`, etc macros described below. A property index can be used with all instances but is typically used to access items of `Array` instances. @@ -726,7 +726,7 @@ Tests whether a given string corresponds to an existing property identifier. Ret *** -### Properties +### Properties This section describes the macros related to accessing properties of objects (or items of arrays), as summarized in Table 1. @@ -741,74 +741,74 @@ This section describes the macros related to accessing properties of objects (or xsGlobal Returns a special instance made of global properties available to scripts - + xsDefine, xsmcDefine Defines a new property of an instance with an identifier and attributes - + xsDefineAt Defines a new property or item of an instance with a key and attributes - + xsHas, xsmcHas Tests whether an instance has a property corresponding to a particular identifier - + xsHasAt Tests whether an instance has a property corresponding to a particular key - + xsHasIndex, xsmcHasIndex Tests whether an instance has a property corresponding to a particular index - + xsGet, xsmcGet Gets a property of an instance by identifier - + xsGetAt, xsmcGetAt Gets a property or an instance by key - + xsGetIndex, xsmcGetIndex Gets a property or an instance by index - + xsSet, xsmcSet Sets a property of an instance with an identifier - + xsSetAt, xsmcSetAt Sets a property of an instance with a key - + xsSetIndex, xsmcSetIndex Sets an property of an instance with an index - + xsDelete, xsmcDelete Deletes a property corresponding to a particular identifier - + xsDeleteAt, xsmcDeleteAt Deletes a property corresponding to a particular key - + xsCall0 ... xsCall7, xsmcCall Calls the function referred to by a property of an instance - + xsNew0 ... xsNew7, xsmcNew Calls the constructor referred to by a property of an instance - + xsTest, xsmcTest Takes a value of any type and determines whether it is true or false - + xsEnumerate Enumerates the properties of an instance - + @@ -829,7 +829,7 @@ You can use the `xsGet`, `xsSet`, `xsDelete`, `xsCall*`, and `xsNew*` macros wit #### xsDefine -To define a new property of an instance with an identifier and attributes, use the `xsDefine` macro. The attributes of the property are set using one or more of the following constants. +To define a new property of an instance with an identifier and attributes, use the `xsDefine` macro. The attributes of the property are set using one or more of the following constants. ```c enum { @@ -841,7 +841,7 @@ enum { xsIsGetter = 32, xsIsSetter = 64, xsChangeAll = 30 -} +} typedef unsigned char xsAttribute; ``` @@ -862,7 +862,7 @@ The `xsDontDelete`, `xsDontEnum`, and `xsDontSet` attributes correspond to the E When a property is created, if the prototype of the instance has a property with the same name, its attributes are inherited; otherwise, by default, a property can be deleted, enumerated, and set, and can be used by scripts. ##### In ECMAScript: - + ```javascript Object.defineProperty(this, "foo", 7, { writable: true, enumerable: true, configurable: true }); ``` @@ -1263,7 +1263,7 @@ To delete a property of an instance corresponding to a particular identifier, us | Arguments | Description | | --- | :-- | -| `theThis` | A reference to the instance that has the property +| `theThis` | A reference to the instance that has the property | `theID` | The identifier of the property to delete ##### In ECMAScript: @@ -1355,9 +1355,9 @@ The `xsmcCall` macro is functionally equivalent to the `xsCall*` macros. The res | Arguments | Description | | --- | :-- | -| `theSlot` | The result slot -| `theThis` | A reference to the instance that will have the property or item -| `theID` | The identifier of the property or item to call +| `theSlot` | The result slot +| `theThis` | A reference to the instance that will have the property or item +| `theID` | The identifier of the property or item to call | ... | Pointers to the slots that are passed as arguments to the constructor followed by a null pointer ##### In ECMAScript: @@ -1379,7 +1379,7 @@ xsmcCall(xsResult, xsGlobal, xsID("foo"), &xsVar(0), NULL); xsmcCall(xsResult, xsThis, xsID_foo, &xsVar(0), NULL); xsmcCall(xsResult, xsThis, 0, &xsVar(1), &xsVar(2), NULL); ``` - + *** @@ -1398,8 +1398,8 @@ When a property or item of an instance is a reference to a constructor, you can | Arguments | Description | | --- | :-- | -| `theThis` | A reference to the instance that has the property or item -| `theID` | The identifier of the property or item to call +| `theThis` | A reference to the instance that has the property or item +| `theID` | The identifier of the property or item to call | `theParam0` ... `theParam6` | The parameter slots to pass to the constructor Returns the result slot of the constructor @@ -1431,9 +1431,9 @@ The `xsmcNew` macro is functionally equivalent to the `xsNew*` macros. The resul | Arguments | Description | | --- | :-- | -| `theSlot` | The result slot of the constructor -| `theThis` | A reference to the instance that has the property or item -| `theID` | The identifier of the property or item to call +| `theSlot` | The result slot of the constructor +| `theThis` | A reference to the instance that has the property or item +| `theID` | The identifier of the property or item to call | ... | Pointers to the slots that are passed as arguments to the constructor followed by a null pointer @@ -1489,7 +1489,7 @@ if (xsTest(xsGet(xsGlobal, xsID_foo)) {} #### xsEnumerate -Use the `xsEnumerate` macro to get an iterator for enumerable instance properties. The iterator provides `next`, `value` and `done` functions to iterate the properties. +Use the `xsEnumerate` macro to get an iterator for enumerable instance properties. The iterator provides `next`, `value` and `done` functions to iterate the properties. **`xsSlot xsEnumerate(xsSlot theObject)`** @@ -1696,7 +1696,7 @@ void xsCleanupFoo(xsMachine* the) { *** The garbage collector is enabled by default. Use `xsEnableGarbageCollection` to enable or disable the garbage collector. - + **`xsSlot xsEnableGarbageCollection(xsBooleanValue enable)`** | Arguments | Description | @@ -1750,7 +1750,7 @@ As shown in the following example, the `xsTry` and `xsCatch` macros are used tog /* Exception thrown here ... */ } catch(e) { - /* ... is caught here. */ + /* ... is caught here. */ throw e } } @@ -1908,14 +1908,14 @@ struct xsMachineRecord { }; ``` -A single machine does not support multiple threads. To work with multiple threads, create one XS runtime machine for each thread, with the host optionally providing a way for the machines to communicate. +A single machine does not support multiple threads. To work with multiple threads, create one XS runtime machine for each thread, with the host optionally providing a way for the machines to communicate. ### Machine Allocation To use the XS runtime you have to create a machine with the `xsCreateMachine` macro, allocating memory for it as required. Its parameters are: -- A structure with members that are essentially parameters specifying what to allocate for the machine. Pass `NULL` if you want to use the defaults. +- A structure with members that are essentially parameters specifying what to allocate for the machine. Pass `NULL` if you want to use the defaults. ```c typedef struct { @@ -1953,11 +1953,11 @@ Returns a machine if successful, otherwise `NULL` Regarding the parameters of the machine that are specified in the `xsCreation` structure: -- A machine uses chunks to store strings, bytecodes, array buffers, big int values, and others. The `initialChunkSize` is the initial size of the memory allocated to chunks. The `incrementalChunkSize` tells the runtime how to expand the memory allocated to chunks. +- A machine uses chunks to store strings, bytecodes, array buffers, big int values, and others. The `initialChunkSize` is the initial size of the memory allocated to chunks. The `incrementalChunkSize` tells the runtime how to expand the memory allocated to chunks. - A machine uses a heap and a stack of slots. The `initialHeapCount` is the initial number of slots allocated to the heap. The `incrementalHeapCount` tells the runtime how to increase the number of slots allocated to the heap. The `stackCount` is the number of slots allocated to the stack. Note that these values are all slots, not bytes. -- A symbol binds a string value and an identifier; see [`xsID`](#xs-id). The `initialKeyCount` is the number of symbols the machine will allocate at initialization. When the keys are exhausted `incrementalKeyCount` keys are added; if `incrementalKeyCount` is 0, the VM aborts when the keys are exhausted. `symbolModulo` is the size of the hash table the machine will use for symbols. The `nameModulo` is the size of the hash table the machine will use for symbol names. +- A symbol binds a string value and an identifier; see [`xsID`](#xs-id). The `initialKeyCount` is the number of symbols the machine will allocate at initialization. When the keys are exhausted `incrementalKeyCount` keys are added; if `incrementalKeyCount` is 0, the VM aborts when the keys are exhausted. `symbolModulo` is the size of the hash table the machine will use for symbols. The `nameModulo` is the size of the hash table the machine will use for symbol names. - Some XS hosts attempt to grow the slot and chunk heaps without limit at runtime to accommodate the memory needs of the hosted scripts; others limit the maximum memory that may be allocated to the machine. For the latter, the `staticSize` defines the total number of bytes that may be allocated for the combination of chunks and slots, which includes the stack. In general, only hosts running on resource constrained devices implement `staticSize`. @@ -1978,7 +1978,7 @@ The `xsDeleteMachine` macro is one of a number of macros described in this docum The following example illustrates the use of `xsCreateMachine` and `xsDeleteMachine`. The `xsMainContext` function called in the example is defined in the next section. ```c -int main(int argc, char* argv[]) +int main(int argc, char* argv[]) { xsCreation aCreation = { 128 * 1024 * 1024, /* initialChunkSize */ @@ -2029,7 +2029,7 @@ Returns a context *** -#### Example +#### Example The following code shows a context being set in the `xsMainContext` function, which was called in the preceding section's example. ```c @@ -2074,40 +2074,40 @@ This section describes the host-related macros of XS in C (see Table 2). An anno

xsNewHostConstructor

Creates a host function or host constructor - + xsNewHostObject Creates a host object - + xsNewHostInstance, xsmcNewHostInstance Creates a host object instance - +

xsGetHostData, xsmcGetHostData

xsSetHostData, xsmcSetHostData

Gets or sets the data in a host object - +

xsGetHostChunk, xsmcGetHostChunk

xsSetHostChunk, xsmcSetHostChunk

Gets or sets the data as a chunk in a host object - + xsSetHostDestructor Sets the destructor for a host object - +

xsBeginHost

xsEndHost

Used together to set up and clean up a stack frame, so that you can use all the macros of XS in C in between - + @@ -2146,7 +2146,7 @@ Creates a host constructor, and returns a reference to the new host constructor #### xsNewHostObject -A *host object* is a special kind of object with data that can be directly accessed only in C. The data in a host object is invisible to scripts. +A *host object* is a special kind of object with data that can be directly accessed only in C. The data in a host object is invisible to scripts. When the garbage collector is about to get rid of a host object, it executes the host object's destructor, if any. No reference to the host object is passed to the destructor: a destructor can only destroy data. @@ -2202,14 +2202,14 @@ Returns the data | Arguments | Description | | --- | :-- | -| `theThis` | A reference to a host object +| `theThis` | A reference to a host object | `theData` | The data to set *** #### xsGetHostChunk and xsSetHostChunk -To get and set the data of a host object as a chunk, use the `xsGetHostChunk` and `xsSetHostChunk` macros. Both throw an exception if the `theThis` parameter does not refer to a host object. Like the memory used by ArrayBuffer and String, chunk memory is allocated and managed by the XS runtime; see the [handle](./handle.md) document for details. +To get and set the data of a host object as a chunk, use the `xsGetHostChunk` and `xsSetHostChunk` macros. Both throw an exception if the `theThis` parameter does not refer to a host object. Like the memory used by ArrayBuffer and String, chunk memory is allocated and managed by the XS runtime; see the [handle](./handle.md) document for details. **`void* xsGetHostChunk(xsSlot theThis)`
`void* xsmcGetHostChunk(xsSlot theThis)`** @@ -2228,10 +2228,10 @@ Returns the data | Arguments | Description | | --- | :-- | | `theThis` | A reference to a host object -| `theData` | The data to set or `NULL` to leave the chunk data uninitialized +| `theData` | The data to set or `NULL` to leave the chunk data uninitialized | `theSize` | The size of the data in bytes -> Note that an object has either host data or a host chunk but never both. +> Note that an object has either host data or a host chunk but never both. *** @@ -2244,14 +2244,14 @@ To set the destructor of a host object (or to clear the destructor, by passing ` | Arguments | Description | | --- | :-- | -| `theThis` | A reference to a host object +| `theThis` | A reference to a host object | `theDestructor` | The destructor to be executed by the garbage collector, or `NULL` to clear the destructor *** #### xsBeginHost and xsEndHost -Use the `xsBeginHost` macro to establish a new stack frame and the `xsEndHost` macro to remove it. +Use the `xsBeginHost` macro to establish a new stack frame and the `xsEndHost` macro to remove it. **`void xsBeginHost(xsMachine* the)`**
**`void xsEndHost(xsMachine* the)`** @@ -2281,7 +2281,7 @@ The `prototype` is a host object which includes the native destructor `xs_file_d This example adds the `close` function to the prototype after creating the constructor. It may be added before instead. -This example also adds a getter accessor function for the property `isOpen`. +This example also adds a getter accessor function for the property `isOpen`. ```c #define kPrototype (0) @@ -2476,7 +2476,7 @@ void xs_rectangle_union(xsMachine *the) } ``` -Standalone functions -- functions that are not part of a class -- can also be implemented in C. The `@` syntax extension is used where the function body normally appears. +Standalone functions -- functions that are not part of a class -- can also be implemented in C. The `@` syntax extension is used where the function body normally appears. ```c function restart() @ "xs_restart"; @@ -2522,34 +2522,34 @@ The value of `xsThis` in the implementation of `xs_restart` matches the receiver ## License Copyright (c) 2016-2023 Moddable Tech, Inc. - + This file is part of the Moddable SDK Runtime. - + The Moddable SDK Runtime is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + The Moddable SDK Runtime is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with the Moddable SDK Runtime. If not, see . - This file incorporates work covered by the following copyright and - permission notice: + This file incorporates work covered by the following copyright and + permission notice: Copyright (C) 2010-2016 Marvell International Ltd. Copyright (C) 2002-2010 Kinoma, Inc. - + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/documentation/xs/XS linker warnings.md b/documentation/xs/XS linker warnings.md index 0012d84c33..aa62bd5319 100644 --- a/documentation/xs/XS linker warnings.md +++ b/documentation/xs/XS linker warnings.md @@ -4,9 +4,9 @@ Revised: November 9, 2019 ## Preload -The XS linker can preload modules by executing their body at link time. The resulting closures and objects will be in ROM at run time. +The XS linker can preload modules by executing their body at link time. The resulting closures and objects will be in ROM at run time. -XS supports an aliasing mechanism to allow such closures and objects to be modified at run time. Modified closures and objects are aliased in RAM. +XS supports an aliasing mechanism to allow such closures and objects to be modified at run time. Modified closures and objects are aliased in RAM. But the aliasing mechanism has a cost, even if closures and objects are never modified: XS uses one pointer for each aliasable closure and object. @@ -29,11 +29,11 @@ Preloaded modules are shared by all compartments, their bodies are considered as Here is a simple `"test"` module which exports one object: export const o = { p: 0 }; - + If the `"test"` module is preloaded, the XS linker reports: ### warning: "test": o: not frozen - + The fix is: export const o = Object.freeze({ p: 0 }); @@ -41,7 +41,7 @@ The fix is: Objects are checked recursively. export const o = Object.freeze({ p: { q: 0 } }); - + The XS linker reports: ### warning: "test": o.p: not frozen @@ -55,8 +55,8 @@ Using the non standard deep freeze feature of XS, the fix is: Here is a simple `"test"` module which exports one function that returns a variable in the module scope: let v = 1; - export function f(a) { - return v; + export function f(a) { + return v; } If the `"test"` module is preloaded, the XS linker reports: @@ -66,28 +66,28 @@ If the `"test"` module is preloaded, the XS linker reports: The fix is: const v = 1; - export function f() { - return v; + export function f() { + return v; } Closures and objects are checked together. For instance: - const o = { p: 0 }; - export function f() { - return o; + const o = { p: 0 }; + export function f() { + return o; } - + The XS linker reports: ### warning: "test": f() o: not frozen The fix is: - const o = Object.freeze({ p: 0 }); - export function f() { - return o; + const o = Object.freeze({ p: 0 }); + export function f() { + return o; } - + ## Globals Preloaded modules can modify the global scope. The resulting object will be in ROM at runtime and will be used to initialize the global scope of the Moddable app (a.k.a. the SES start-compartment). The XS linker also reports warnings about globals. @@ -95,7 +95,7 @@ Preloaded modules can modify the global scope. The resulting object will be in R Here is a simple `"test"` module which adds one object to the global scope: globalThis.g = { p: 0 }; - + If the `"test"` module is preloaded, the XS linker reports: ### warning: globalThis.g: not frozen @@ -114,19 +114,19 @@ Most instances of built-ins classes can be preloaded but cannot be aliased. Once |--------------|---------|-------|------------------| | Array | Yes | Yes | - | | ArrayBuffer\* | Yes | No | - | -| AsyncGenerator\* | No | No | +| AsyncGenerator\* | No | No | | Boolean | Yes | No | - | | DataView | Yes | No | set | | Date | Yes | No | setDate, setFullYear, setHours, setMilliseconds, setMinutes, setMonth, setSeconds, setTime, setYear, setUTCDate, setUTCFullYear, setUTCHours, setUTCMilliseconds, setUTCMinutes, setUTCMonth, setUTCSeconds | | Error | Yes | No | - | | FinalizationGroup | Yes | No | cleanupSome, register, unregister | | Function\* | Yes | No | - | -| Generator\* | No | No | +| Generator\* | No | No | | Map | Yes | No | clear, delete, set | | Number | Yes | No | - | | Promise | Yes | No | - | | Proxy | Yes | No | revoke | -| RegExp | Yes | No | +| RegExp | Yes | No | | Set | Yes | No | add, clear, delete | | String | Yes | No | - | | Symbol | Yes | No | - | diff --git a/documentation/xs/handle.md b/documentation/xs/handle.md index fa9739f5c1..109bfcadbc 100644 --- a/documentation/xs/handle.md +++ b/documentation/xs/handle.md @@ -5,13 +5,13 @@ Revised: May 17, 2017 ## Objective -To develop frameworks for microcontrollers with XS, the most significant constraint is RAM. +To develop frameworks for microcontrollers with XS, the most significant constraint is RAM. The XS linker prepares most classes, prototypes, functions and byte codes to be accessed straightly from ROM. All the ECMAScript 2017 features, and most modules composing the frameworks are there, instantaneously available and requiring just a few KB of RAM. -For everything that is created at runtime, applications rely on the XS garbage collector to manage memory. XS divides memory into two zones: the slots and the chunks. +For everything that is created at runtime, applications rely on the XS garbage collector to manage memory. XS divides memory into two zones: the slots and the chunks. -Slots have a fixed size (16 bytes on a 32-bit processor) and cannot move. Chunks have a variable size and can move. The XS garbage collector can compact chunks when necessary, which is a life saver for processors without an MMU. +Slots have a fixed size (16 bytes on a 32-bit processor) and cannot move. Chunks have a variable size and can move. The XS garbage collector can compact chunks when necessary, which is a life saver for processors without an MMU. Slots are used for anything that fits: booleans, dates, instances, numbers, properties, references, symbols, etc. Chunks are used for everything else: byte codes, arrays, strings, etc. @@ -33,14 +33,14 @@ The `HANDLE` is a pointer to the `DATA` part of a `HOST` slot. The `DATA` part o C based objects are chunks. They can contain anything, for instance colors, coordinates, dimensions, etc. Notice that for such values, C based objects are also saving memory since they can pack several values into one chunk instead of using one slot for each value. The memory savings by applying this approach can be considerable as a JavaScript property requires a slot (16 bytes on a typical MCU) which is larger than a native boolean (1 byte), integer (2 or 4 bytes), or even a floating point double (8 bytes). -From JavaScript, C based objects are just host objects and are accessed thru the `INSTANCE` slot like any host objects. Thru the `PROTOTYPE` part of the `INSTANCE` slot, frameworks provides getters, setters and methods so applications can access and manipulate values as usual. +From JavaScript, C based objects are just host objects and are accessed thru the `INSTANCE` slot like any host objects. Thru the `PROTOTYPE` part of the `INSTANCE` slot, frameworks provides getters, setters and methods so applications can access and manipulate values as usual. ## Implementation C based objects reference other C based object thru handles, i.e. a chunk can contain a handle to another chunk. For instance a content accesses its container with (*content)->container - + That is essential for to achieve maximum performance. For instance, the layout hierarchy is traversed a lot when animating a screen at 30 fps. What happens when XS collects garbage if a handle inside a chunk is the only reference to a C based object? @@ -53,6 +53,6 @@ C based objects implement host `HOOKS`, which are XS garbage collector callbacks ## Example -Please look at the *Piu* sources, which implement part of the *KinomaJS* programming interface on microcontrollers using the *Commodetto* graphics library. +Please look at the *Piu* sources, which implement part of the *KinomaJS* programming interface on microcontrollers using the *Commodetto* graphics library. diff --git a/documentation/xs/mods.md b/documentation/xs/mods.md index ebfa7fbe51..25832290d0 100644 --- a/documentation/xs/mods.md +++ b/documentation/xs/mods.md @@ -8,7 +8,7 @@ Mods are simple to create but the technology behind them is complex. This articl ## Key Characteristics of Mods -Mods are a tool to extend the capabilities of IoT products. It is rare today for an IoT product to support extensions, and when they do it is through native code. Using JavaScript as the foundation for mods not only makes it feasible to support extensibility in many more products, it empowers many more users to do so. +Mods are a tool to extend the capabilities of IoT products. It is rare today for an IoT product to support extensions, and when they do it is through native code. Using JavaScript as the foundation for mods not only makes it feasible to support extensibility in many more products, it empowers many more users to do so. - **Mods are portable** - The JavaScript language was designed from the start to be independent of both the host operating system and the host hardware. The Moddable SDK follows that by providing APIs that are consistent across devices. This portability is critical so that developers can use their knowledge and experience across devices from many different manufacturers, rather than needing to learn new development tools, a new language, and new APIs for each IoT product. - **Mods are standard** - IoT products are built using standards -- from standard electrical connectors to standard Wi-Fi -- to ensure they are reliable, safe, and can interoperate with products from different manufacturers. Mods follow this proven pattern by using modern industry-standard JavaScript (ECMAScript 2020) as their programming language. Moddable is helping to standardize APIs for IoT products through the Ecma TC53 committee, ECMAScript Modules for Embedded Systems. @@ -52,7 +52,7 @@ trace(`Software version ${config.version}\n`); ``` The mod contains a single data file, a text file with a short message. - + ``` Hello, mod. ``` @@ -157,7 +157,7 @@ if (Modules.has("mod")) Modules.importNow("mod"); ``` -The `importNow` function loads the module and executes the module's body, similar to calling dynamic `import`, though `importNow` is synchronous. +The `importNow` function loads the module and executes the module's body, similar to calling dynamic `import`, though `importNow` is synchronous. The `importNow` function returns the module's default export. Consider the following mod that exports several functions through its default export. @@ -249,7 +249,7 @@ For additional details on stripping language features, see the [Strip](https://g When a mod uses a JavaScript language feature that has been stripped, a "dead strip" exception is generated and the virtual machine terminates execution. ### Securing a Mod -Mods are powerful because they have access to the same modules and global variables as the host. This means that a mod is likely able to perform all of the same operations as the host. For a simple host that only prepares an environment for the mod to run in, this is not a problem. However, some hosts want to limit what a mod can do to ensure the integrity of operation of the host. These IoT product hosts want to ensure that the mod can only perform those operations the host chooses to allow. +Mods are powerful because they have access to the same modules and global variables as the host. This means that a mod is likely able to perform all of the same operations as the host. For a simple host that only prepares an environment for the mod to run in, this is not a problem. However, some hosts want to limit what a mod can do to ensure the integrity of operation of the host. These IoT product hosts want to ensure that the mod can only perform those operations the host chooses to allow. Restricting a script from access to certain capabilities is common. Every web browser ensures the integrity of the user's computer by restricting scripts in many ways. For example, scripts cannot normally access the user's file system. @@ -270,13 +270,13 @@ let c = new Compartment( let exports = c.importNow("mod"); ``` -The first argument to the `Compartment` constructor relates to global variables inside the compartment and is described in the following section. The second argument is the compartment's module map. It performs two functions. First, it determines which modules are available to be imported by scripts running inside the compartment. Second, it allows remapping module specifiers to change how a module is accessed inside the compartment. +The first argument to the `Compartment` constructor relates to global variables inside the compartment and is described in the following section. The second argument is the compartment's module map. It performs two functions. First, it determines which modules are available to be imported by scripts running inside the compartment. Second, it allows remapping module specifiers to change how a module is accessed inside the compartment. The module map above allows only the module named "mod" to be imported inside the compartment. There is no remapping of module specifiers. The property name on the left ("mod") is the module specifier inside the compartment and the value on the right (also "mod") is the module specified in the host. The call to the `importNow` method loads the module "mod" inside of compartment `c`. Because of the module map, the mod cannot import any of the modules from the host. If it tries to do so, the import fails as if the module is not present. -The compartment map below is changed to use remapping. +The compartment map below is changed to use remapping. ```js let c = new Compartment( @@ -353,15 +353,15 @@ Array.prototype.push = function(...elements) { This kind of global patch of built-in objects is called a [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch). It is a technique that allows one script to attack another. In SES, this kind of attack is not possible through the primordial objects because they are frozen, making it impossible to change existing properties. If a script running in a compartment attempts to replace the `push` function, an exception is thrown. ## Behind the Scenes -Mods are easy to use, which makes it easy to overlook the many complex details involved in making them work. This section describes implementation details that may be important when working with mods. +Mods are easy to use, which makes it easy to overlook the many complex details involved in making them work. This section describes implementation details that may be important when working with mods. ### Building Mods -`mcrun` converts the mod's JavaScript source code and data into a single binary file, an XS Archive (.xsa extension). The archive format is designed so JavaScript byte code executes directly from flash storage without having to be copied into memory. +`mcrun` converts the mod's JavaScript source code and data into a single binary file, an XS Archive (.xsa extension). The archive format is designed so JavaScript byte code executes directly from flash storage without having to be copied into memory. The JavaScript modules are precompiled to XS byte code, so no source code is deployed to the target device. This allows the device to begin executing the mod without needing to parse the JavaScript source code first. The image, font, and audio resources in the manifest are transformed to a format compatible with the target device following the manifest [resource rules](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/tools/manifest.md#resources). - + While the source code to the mod is platform independent, the binary format of the mod is not. The pixel format and rotation of the images is optimized for a specific host, the XS byte code generated is for a specific version of the XS engine, etc. The archive is not a general purpose distribution format for mods. The `mcrun` tool builds the mod without knowledge of the symbol table of the mod host. XS byte code references symbols by a 16-bit ID. The first time a mod is run by a mod host, XS automatically updates the symbol ID values in the mod's byte code so they match the host IDs. This process is very fast. However, it does mean that the remapped mod data on the device cannot be copied and installed on another device. Instead, a fresh copy of the mod must be installed. When the ID remapping is performed, XS stores a hash of the mod host's symbol table so that if the host is updated independently of the mod, the mod will not attempt to run (as the symbol IDs could be incorrect). diff --git a/documentation/xs/preload.md b/documentation/xs/preload.md index 876d23a798..c7b0fc80c9 100644 --- a/documentation/xs/preload.md +++ b/documentation/xs/preload.md @@ -37,7 +37,7 @@ class CountingLog { trace(`${this.count++}: ${msg}\n`); } } - + export default CountingLog; ``` @@ -47,14 +47,14 @@ Here's another example module, one that imports `CountingLog` and extends it to ```js import CountingLog from "countinglog"; - + class CountingDateLog extends CountingLog { log(msg) { trace(`${new Date} `); super.log(msg); } } - + export default CountingDateLog; ``` @@ -70,7 +70,7 @@ Because XS allows objects stored in flash to be modified, code that modifies the ```js import CountingLog from "countinglog"; - + CountingLog.prototype.reset = function() { this.count = 0; } @@ -90,7 +90,7 @@ class CountingLog { } } Object.freeze(CountingLog.prototype); - + export default CountingLog; ``` @@ -104,7 +104,7 @@ JavaScript applications often use objects to store data. Here's an example from ```js const Colors = [ {name: "blue", value: 0x0000FF}, - {name: "white", value: 0xFFFF00}, + {name: "white", value: 0xFFFF00}, {name: "red", value: 0xFF0000}, {name: "green", value: 0x00FF00}, {name: "purple", value: 0xFF00FF}, @@ -133,7 +133,7 @@ Unfortunately, that obscures the data. Here's another approach: ```js const Colors = [ {name: "blue", value: 0x0000FF}, - {name: "white", value: 0xFFFF00}, + {name: "white", value: 0xFFFF00}, ... ]; Object.freeze(Colors); @@ -148,7 +148,7 @@ Freezing objects is more common using XS than in other JavaScript environments. ```js const Colors = [ {name: "blue", value: 0x0000FF}, - {name: "white", value: 0xFFFF00}, + {name: "white", value: 0xFFFF00}, ... ]; Object.freeze(Colors, true); @@ -178,7 +178,7 @@ class CountingLog { } } Object.freeze(CountingLog.prototype); - + export default CountingLog; ``` @@ -187,7 +187,7 @@ When this module is preloaded, the value of the `count` variable is frozen in RO Use `const` to declare module variables that are not intended to be modified at runtime. Declaring a module variable with `const` conveys to XS that the variable cannot be modified. This saves RAM by eliminating the pointer otherwise needed to allow the variable to be modified. ## What Cannot be Preloaded -Preloading occurs on the build machine, not the target device. That limits the operations that may be performed during preload. +Preloading occurs on the build machine, not the target device. That limits the operations that may be performed during preload. ### Native Functions Because the build is for the target device, not the build machine, any native functions cannot be executed as they expect a different environment, perhaps even a different instruction set. If a module attempts to call a native function, an error is generated during the build. @@ -196,7 +196,7 @@ For example, the following fails to preload because `Digital.write` is a native ```js import Digital from "pins/digital"; - + Digital.write(1, 0); ``` @@ -211,7 +211,7 @@ class Example { static aNativeFunction() @ "xs_nativefunction"; } ``` - + Because calling a native function is not possible, this generates an error at build time: ```js @@ -255,7 +255,7 @@ These objects cannot be stored in flash memory: - Generator - SharedArrayBuffer -In the future XS may support storing additional built-in objects in flash memory. For details on built-in objects stored in flash memory see the [XS Linker Warnings](./XS%20linker%20warnings.md) document. +In the future XS may support storing additional built-in objects in flash memory. For details on built-in objects stored in flash memory see the [XS Linker Warnings](./XS%20linker%20warnings.md) document. These objects cannot be stored in flash. However, they maybe used during preload as long as they do not need to be stored. For example, code that executes a part of preload can safely use `RegExp` as long as there are no regular expression instances remaining when the preload phase ends. @@ -266,9 +266,9 @@ Here's a trivial example of an application that turns on one LED using a Digital ```js import Digital from "pins/digital: - + let toggle = false; - + Digital.write(1, true); Timer.repeat(() => { toggle = !toggle; @@ -280,10 +280,10 @@ In the Moddable SDK runtime, if the `main` module returns a function, that funct ```js import Digital from "pins/digital: - + export default function() { let toggle = false; - + Digital.write(1, true); Timer.repeat(() => { toggle = !toggle; @@ -328,14 +328,14 @@ const roots = [ 1.7320508076, 2, 2.2360679775, - 2.4494897428, + 2.4494897428, 2.6457513111, 2.8284271247, 3, 3.1622776602 ]; Object.freeze(roots); - + function fastSquareRootToTen(x) { return roots[x]; } @@ -348,7 +348,7 @@ const roots = []; for (let i = 0; i <= 10; i++) roots[i] = Math.sqrt(i) Object.freeze(roots); - + function fastSquareRootToTen(x) { return roots[x]; } @@ -356,10 +356,10 @@ function fastSquareRootToTen(x) { This technique may be applied to perform more sophisticated calculations and to generate data structures more complex than arrays. -## Using xsbug to Check Preloaded Modules +## Using xsbug to Check Preloaded Modules Determining if all the modules in a project are set to preload is difficult by inspecting the source code. The xsbug debugger has two features to help. -In the Instruments pane, there is a "Modules loaded" area that shows the number of runtime loaded modules for each second of execution. In most projects this number should be either one or zero. +In the Instruments pane, there is a "Modules loaded" area that shows the number of runtime loaded modules for each second of execution. In most projects this number should be either one or zero. The module pane shows a list of all loaded modules and indicates by color which of the modules are preloaded. Modules which are preloaded are shown in blue and those loaded at runtime are shown in black. diff --git a/documentation/xs/xsbug.md b/documentation/xs/xsbug.md index a0772f1153..f0fc0b850d 100644 --- a/documentation/xs/xsbug.md +++ b/documentation/xs/xsbug.md @@ -33,7 +33,7 @@ Figure 2 shows the Breakpoints tab view. Select the first tab (highlighted in re To disable/enable a breakpoint, click on the breakpoint in the breakpoint tab then select the **Disable Breakpoint** or **Enable Breakpoint** option in the **Debug** menu. -To add files and folders to **xsbug**, select the **Open File...** and **Open Folder...** items in the **File** menu, or drag and drop files and folders into the **xsbug** window. +To add files and folders to **xsbug**, select the **Open File...** and **Open Folder...** items in the **File** menu, or drag and drop files and folders into the **xsbug** window. To remove files and folders from **xsbug**, use the **Close** ![](../assets/xsbug/close.png) button in the header of a files and folders panel. @@ -43,8 +43,8 @@ To remove files and folders from **xsbug**, use the **Close** ![](../assets/xsbu The left pane displays: -* The **Breakpoints** themselves. Tap a row in this panel to see where the breakpoint is. In the header of this panel, there is a **Trash** ![](../assets/xsbug/trash.png) button to clear all breakpoints. -* The **Search** panel. Use this to recursively search all the files in all the folders added to **xsbug**. +* The **Breakpoints** themselves. Tap a row in this panel to see where the breakpoint is. In the header of this panel, there is a **Trash** ![](../assets/xsbug/trash.png) button to clear all breakpoints. +* The **Search** panel. Use this to recursively search all the files in all the folders added to **xsbug**. * Zero or more files and folders panels. Tap folder rows to browse, select a file row to display the file. The right pane displays: @@ -54,7 +54,7 @@ The right pane displays: ## File Pane -Figure 3. shows the File pane (highlighted in red). Selecting a row in the **Breakpoints** or **Calls** panels, or selecting a file in a folder panel opens a right pane with source code. +Figure 3. shows the File pane (highlighted in red). Selecting a row in the **Breakpoints** or **Calls** panels, or selecting a file in a folder panel opens a right pane with source code. **Figure 3.** File pane @@ -65,12 +65,12 @@ In the header of the pane: * Tapping the parts of the path open folders in the Finder or Explorer. * The **Edit** ![](../assets/xsbug/edit.png) button opens the file in its default editor. * The **Find** ![](../assets/xsbug/find.png) button extends the header with a field to search the file. -* The **Close** ![](../assets/xsbug/close.png) button closes the file pane. +* The **Close** ![](../assets/xsbug/close.png) button closes the file pane. ## Preferences Pane -Figure 4. shows the Preferences pane. Selecting the **Preferences** item from the **xsbug** menu opens a right pane with preferences panels. +Figure 4. shows the Preferences pane. Selecting the **Preferences** item from the **xsbug** menu opens a right pane with preferences panels. **Figure 4.** Preferences pane diff --git a/documentation/xs/xst.md b/documentation/xs/xst.md index 2142fc2dcb..9f927bfea1 100644 --- a/documentation/xs/xst.md +++ b/documentation/xs/xst.md @@ -4,26 +4,26 @@ ## Build -### Linux +### Linux cd $MODDABLE/xs/makefiles/lin make -### macOS +### macOS cd $MODDABLE/xs/makefiles/mac make - -### Windows + +### Windows cd %MODDABLE%\xs\makefiles\win build ## Download -You can use the [jsvu CLI](https://github.com/GoogleChromeLabs/jsvu) to install or update **xst**. +You can use the [jsvu CLI](https://github.com/GoogleChromeLabs/jsvu) to install or update **xst**. -You can also download the latest versions of `xst` +You can also download the latest versions of `xst` from the [moddable-xst](https://github.com/Moddable-OpenSource/moddable-xst/releases) repository into a directory that is on your `PATH` @@ -37,7 +37,7 @@ from the [moddable-xst](https://github.com/Moddable-OpenSource/moddable-xst/rele - `-s`: `strings` are paths to scripts - `-v`: print XS version -Without the `-e`, `-m` or `-s` options, `strings` are paths to **test262** cases or directories. +Without the `-e`, `-m` or `-s` options, `strings` are paths to **test262** cases or directories. ### eshost @@ -50,7 +50,7 @@ To test XS with **eshost**, install the [eshost CLI](https://github.com/bterlson ### test262 To test XS with **test262**, clone [test262](https://github.com/tc39/test262) and change the directory to the `test` directory inside the `test262` directory. For instance: - + cd ~/test262/test xst language/block-scope xst built-ins/TypedArrays/buffer-arg-* diff --git a/examples/commodetto/readme.md b/examples/commodetto/readme.md index 67bb26e45d..dc3e0b4315 100755 --- a/examples/commodetto/readme.md +++ b/examples/commodetto/readme.md @@ -3,7 +3,7 @@ Copyright 2021 Moddable Tech, Inc.
Revised: November 4, 2021 -These examples demonstrate how to use features of [Commodetto](../../documentation/commodetto/commodetto.md), a bitmap graphics library that provides a 2D graphics API. Commodetto includes the lightweight [Poco rendering engine](../../documentation/commodetto/poco.md), a display list renderer able to efficiently render a single scanline at a time, saving considerable memory by eliminating the need for a frame buffer. +These examples demonstrate how to use features of [Commodetto](../../documentation/commodetto/commodetto.md), a bitmap graphics library that provides a 2D graphics API. Commodetto includes the lightweight [Poco rendering engine](../../documentation/commodetto/poco.md), a display list renderer able to efficiently render a single scanline at a time, saving considerable memory by eliminating the need for a frame buffer. Most of the examples are designed for a QVGA (320x240) screen, but many work on a variety of screen sizes. All of the examples in this folder run on the desktop simulator with the exception of the `mini-drag` example. @@ -13,7 +13,7 @@ This document provides a brief description of each example and a preview of each - **Text:** `text`, `text-ticker`, `cfe8x8`, `cfeNFNT` - **Animation:** `docs`, `progress`, `text-ticker` - **Touch input:** `mini-drag` -- **Networking:** `jpeghttp`, `jpegstream`, `epaper-mini-travel-time`, +- **Networking:** `jpeghttp`, `jpegstream`, `epaper-mini-travel-time`, *** @@ -141,7 +141,7 @@ The `outline/random-triangles` example demonstrates using both stroked and fille ### `pngdisplay` -The `pngdisplay` allows you to use the curl command line tool to push PNG images to the display. Created for use by user interface designers, not developers. +The `pngdisplay` allows you to use the curl command line tool to push PNG images to the display. Created for use by user interface designers, not developers. > See the [blog post](https://blog.moddable.com/blog/pngdisplay/) Pushing PNG Images to a Display for more information about this example. @@ -159,7 +159,7 @@ The `progress` example displays high frame rate animations of progress bars and ![](https://www.moddable.com/assets/commodetto-gifs/rotated.png) -The `rotated` example demonstrates how to define the rotation of the screen. This example rotates 90 degrees; 0, 180, and 270 degree rotation is also supported. +The `rotated` example demonstrates how to define the rotation of the screen. This example rotates 90 degrees; 0, 180, and 270 degree rotation is also supported. *** diff --git a/examples/drivers/peripherals/rtc/readme.md b/examples/drivers/peripherals/rtc/readme.md index 5f35e94361..ddd6a6228b 100644 --- a/examples/drivers/peripherals/rtc/readme.md +++ b/examples/drivers/peripherals/rtc/readme.md @@ -30,6 +30,6 @@ in the `manifest.json` file, change the `include` for your device. For example: ``` "include": [ - "$(MODDABLE)/modules/drivers/peripherals/ds1307/manifest.json" + "$(MODDABLE)/modules/drivers/peripherals/ds1307/manifest.json" ] ``` diff --git a/examples/drivers/readme.md b/examples/drivers/readme.md index 31d4a45d0b..f797789aa9 100644 --- a/examples/drivers/readme.md +++ b/examples/drivers/readme.md @@ -73,7 +73,7 @@ Demonstrates use of the the Hitachi HD44780 character LCD module. ### [`HMC5883L`](./HMC5883L) -Reads digital compass measurements at 250ms intervals from the I2C [SparkFun Triple Axis Magnetometer Breakout - HMC5883L](https://www.sparkfun.com/products/retired/10530). +Reads digital compass measurements at 250ms intervals from the I2C [SparkFun Triple Axis Magnetometer Breakout - HMC5883L](https://www.sparkfun.com/products/retired/10530). *** ### [`hx711`](./hx711) diff --git a/examples/drivers/sensors/hc-sr04/multiple-sensors/readme.md b/examples/drivers/sensors/hc-sr04/multiple-sensors/readme.md index d0496d677d..6a24043921 100644 --- a/examples/drivers/sensors/hc-sr04/multiple-sensors/readme.md +++ b/examples/drivers/sensors/hc-sr04/multiple-sensors/readme.md @@ -1,5 +1,5 @@ -This example demonstrates how to trigger and read from multiple HC-SR04 sensors in a round-robin fashion. +This example demonstrates how to trigger and read from multiple HC-SR04 sensors in a round-robin fashion. The Echo pins are all connected to a shared bus (ESP32 GPIO 12 by default) while each HC-SR04 needs a separate trigger pin (ESP32 GPIOs 13, 14, and 27 by default). To avoid damage to the HC-SR04 sensors, the Echo pins must be electrically isolated from each other. That can be accomplished with diodes, as shown in the diagram below: -![](circuit.png) \ No newline at end of file +![](circuit.png) diff --git a/examples/io/tcp/readme.md b/examples/io/tcp/readme.md index acaf79a476..e8719602f9 100644 --- a/examples/io/tcp/readme.md +++ b/examples/io/tcp/readme.md @@ -22,6 +22,6 @@ The examples in this directory use the [TCP socket](https://419.ecma-internation The `HTTPRequest`, `WebSocketClient`, and `MQTTClient` classes are designed to use runtime resources efficiently while supporting all the fundamental capabilities of the underlying protocol. They give the most control and the lightest footprint, but as lower-level APIs they are less convenient to use. -The `fetch`, `WebSocket`, and `mqtt` classes provide embedded developers access to familiar, standard APIs from the web platform. They are generally more convenient to use and use more resources (RAM, code size, CPU). +The `fetch`, `WebSocket`, and `mqtt` classes provide embedded developers access to familiar, standard APIs from the web platform. They are generally more convenient to use and use more resources (RAM, code size, CPU). -The choice of which API to use for a project depends on the requirements of that project. For many situations, the standard `fetch`, `WebSocket`, and `mqtt` APIs work well. +The choice of which API to use for a project depends on the requirements of that project. For many situations, the standard `fetch`, `WebSocket`, and `mqtt` APIs work well. diff --git a/examples/js/compartments/readme.md b/examples/js/compartments/readme.md index 95f87c5085..a128d85249 100644 --- a/examples/js/compartments/readme.md +++ b/examples/js/compartments/readme.md @@ -1,3 +1,3 @@ # Compartment Examples -We're working on this to sync with [the TC39 Compartment proposal](https://github.com/tc39/proposal-compartments) and with [Agoric SES compartments](https://github.com/endojs/endo/blob/kris-sketch-api-docs/packages/ses/index.d.ts). We'll update this when it settles down. \ No newline at end of file +We're working on this to sync with [the TC39 Compartment proposal](https://github.com/tc39/proposal-compartments) and with [Agoric SES compartments](https://github.com/endojs/endo/blob/kris-sketch-api-docs/packages/ses/index.d.ts). We'll update this when it settles down. diff --git a/examples/network/aws/moddable-aws-guide.md b/examples/network/aws/moddable-aws-guide.md index 813fe4d1a4..e73a253cb7 100644 --- a/examples/network/aws/moddable-aws-guide.md +++ b/examples/network/aws/moddable-aws-guide.md @@ -105,4 +105,4 @@ Notes: * Change the `` to the endpoint of your AWS MQTT Test Client, which should also be the same value as the `awsEndpoint` variable in your `main.js` (ex:` a2vxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com` * If you don't have `curl` installed on your machine, you can get it from [here](https://everything.curl.dev/get). ​ -### Now you should be able to communicate with AWS using the Moddable SDK! \ No newline at end of file +### Now you should be able to communicate with AWS using the Moddable SDK! diff --git a/examples/pins/audioout/http-stream/readme.md b/examples/pins/audioout/http-stream/readme.md index 08ce9099aa..619de997de 100644 --- a/examples/pins/audioout/http-stream/readme.md +++ b/examples/pins/audioout/http-stream/readme.md @@ -2,7 +2,7 @@ Copyright 2022-2023 Moddable Tech, Inc.
Revised: March 13, 2023 -The `WavStream` and `SBCStream` classes plays audio streams delivered over HTTP. The `WavStream` class plays uncompressed WAV audio files and `Audio/L16`; the `SBCStream` class plays [SBC compressed](https://en.wikipedia.org/wiki/SBC_%28codec%29) audio. SBC is a low-complexity format used primarily by Bluetooth. Its relatively high quality and simple decoder make it well suited for microcontrollers. +The `WavStream` and `SBCStream` classes plays audio streams delivered over HTTP. The `WavStream` class plays uncompressed WAV audio files and `Audio/L16`; the `SBCStream` class plays [SBC compressed](https://en.wikipedia.org/wiki/SBC_%28codec%29) audio. SBC is a low-complexity format used primarily by Bluetooth. Its relatively high quality and simple decoder make it well suited for microcontrollers. The `WavStream` and `SBCStream` classes share a common API but have separate implementations. They uses the following modules: diff --git a/examples/piu/readme.md b/examples/piu/readme.md index 13506ce1be..9407006e6e 100755 --- a/examples/piu/readme.md +++ b/examples/piu/readme.md @@ -20,7 +20,7 @@ This document provides a brief description of each example and a preview of each ### `backlight` -The `backlight` example allows you to adjust the backlight brightness on Moddable Two. +The `backlight` example allows you to adjust the backlight brightness on Moddable Two. > For more information about the backlight, see the **Backlight** section of the [Moddable Two documentation](https://github.com/Moddable-OpenSource/moddable/blob/public/documentation/devices/moddable-two.md#backlight). @@ -170,7 +170,7 @@ The `keyboard` example demonstrates the use of the keyboard module to create an ![](http://www.moddable.com/assets/piu-gifs/list.gif) -The `list` example uses a Piu `Port` object to create a scrolling list of items that may be tapped. +The `list` example uses a Piu `Port` object to create a scrolling list of items that may be tapped. *** @@ -259,7 +259,7 @@ The `preferences` example demonstrates how to set preferences that are saved acr ![](http://www.moddable.com/assets/piu-gifs/scroller.gif) -The `scroller` example shows how to create vertical and horizontal scrolling content. Tap the title bar to toggle between the two directions. +The `scroller` example shows how to create vertical and horizontal scrolling content. Tap the title bar to toggle between the two directions. *** @@ -338,4 +338,4 @@ The `weather` and `mini-weather` examples display the weather forecast for five The `wifi-config` example allows the user to configure the Wi-Fi network by selecting from a list of available networks. The on-screen keyboard is used to enter the password for secure networks. -*** \ No newline at end of file +*** diff --git a/examples/readme.md b/examples/readme.md index 68e15ed265..9a7dba976d 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -26,12 +26,12 @@ The `mcconfig` command line tool builds Moddable apps. To use it, open a termina cd $MODDABLE/examples/piu/balls mcconfig -m - + On Windows, use the **Developer Command Prompt for VS 2017** to build apps: cd %MODDABLE%\examples\piu\balls mcconfig -m - + By default, `mcconfig` generates a release build that targets the host platform. These are common command line options: - `-d`: build a debug instrumented version @@ -54,7 +54,7 @@ Also note that `mcconfig` automatically deploys apps to target devices. For many The `-p` command line option specifies the target platform/subplatform you are building for. For example, to build a release app that targets Moddable One: mcconfig -m -p esp/moddable_one - + To build a debug app that targets ESP32 devices: mcconfig -d -m -p esp32 @@ -80,7 +80,7 @@ For example, to build a debug version of the `balls` example app with the 8-bit ### Screen rotation -Some example apps are designed to render on a rotated screen. Use the `-r` command line option to specify the target rotation angle: +Some example apps are designed to render on a rotated screen. Use the `-r` command line option to specify the target rotation angle: - `-r 0`: no rotation (default) - `-r 90`: 90 degree rotation @@ -97,7 +97,7 @@ To build the `progress` app to run at 180 degrees rotation on the host platform: cd $MODDABLE/examples/commodetto/progress mcconfig -d -m -r 180 - + ### Wi-Fi configuration @@ -114,7 +114,7 @@ To build and run the `sntp` app for the open network `Free Wifi`: cd $MODDABLE/examples/network/sntp mcconfig -d -m -p esp ssid="Free WiFi" - + ### Screen driver configuration @@ -132,7 +132,7 @@ The remainder of this section explains how to do these steps. To run the `text` app on an ESP8266 device with a [LPM013M126A](../modules/drivers/lpm013m126a) 8-color display: cd $MODDABLE/examples/commodetto/text - mcconfig -d -m -p esp screen=lpm013m126a + mcconfig -d -m -p esp screen=lpm013m126a To run the `map-puzzle` app on an ESP8266 device with a [FT6206](../modules/drivers/ft6206) multi-touch controller: cd $MODDABLE/examples/piu/map-puzzle @@ -160,7 +160,7 @@ To build an app for the `ft6206` touch controller driver, modify both the `confi "screen": "ili9341", "touch": "ft6206" } - + "include": [ "$(MODDABLE)/modules/drivers/ili9341/manifest.json", "$(MODDABLE)/modules/drivers/ft6206/manifest.json" diff --git a/modules/commodetto/gif/readme.md b/modules/commodetto/gif/readme.md index 4b3507f273..52acc7e8b3 100644 --- a/modules/commodetto/gif/readme.md +++ b/modules/commodetto/gif/readme.md @@ -10,7 +10,7 @@ Most GIF implementations for microcontrollers decode directly to the frame buffe The Commodetto animated GIF decoder has several special decoding modes to significantly reduce the amount of memory required to decode many animated GIF sequences. -Because of the increased memory requirements, the Commodetto animated GIF decoder is not practical on all microcontrollers. It works very well on an ESP32 (with no external RAM) and Pico (RP2040) for images that are about 200 pixels on a side. +Because of the increased memory requirements, the Commodetto animated GIF decoder is not practical on all microcontrollers. It works very well on an ESP32 (with no external RAM) and Pico (RP2040) for images that are about 200 pixels on a side. ## Examples @@ -47,7 +47,7 @@ The `width` and `height` properties of the reader instance provide the dimension The `duration` property is the total length of the animation in milliseconds. The `frameCount` is the total number of frames in the animation. ### Decoding a frame -To decode an image, call `next`. When the end of the animated frame sequence is reached, the decoder automatically loops back to the start. +To decode an image, call `next`. When the end of the animated frame sequence is reached, the decoder automatically loops back to the start. ```js reader.next(); @@ -122,7 +122,7 @@ poco.drawBitmapWithKeyColor(reader, 0, 0, reader.transparentColor); Note that the `fillRectangle` call draws behind the animated GIF. Your code can draw anything behind the GIF, such as a pattern or a logo or even another animation. It is safe to use `drawBitmapWithKeyColor`. ### Reducing memory use -A GIF image contains between 2 and about 16 million colors. Images with many colors must be stored at 16-bits per pixel, which uses quite a bit of memory. The Commodetto GIF decoder is also able to decode GIF images to 8-bit, 4-bit, and 1-bit pixels. The decoder automatically determines the format that uses the least memory while maintaining full color fidelity. Thee bitmap format used may always be drawn using `poco.drawBitmapWithKeyColor`. The format of the bitmap used is available from the `pixelFormat` property of the GIF Reader instance. +A GIF image contains between 2 and about 16 million colors. Images with many colors must be stored at 16-bits per pixel, which uses quite a bit of memory. The Commodetto GIF decoder is also able to decode GIF images to 8-bit, 4-bit, and 1-bit pixels. The decoder automatically determines the format that uses the least memory while maintaining full color fidelity. Thee bitmap format used may always be drawn using `poco.drawBitmapWithKeyColor`. The format of the bitmap used is available from the `pixelFormat` property of the GIF Reader instance. Some applications may wish to force decoding to a specific format, overriding the automatic format detection. This may generate an image which does not render correctly, but should never crash. To force decoding to a particular format, pass the pixel format to the `ReadGIF` constructor as part of the optional options argument. The following example shows requesting pixels in RGB565 little-endian format: @@ -161,4 +161,4 @@ The following table describes the properties available on the GIF reader instanc ## Thank you -The core GIF decoder is [GIF Animator](https://github.com/bitbank2/AnimatedGIF) by [Larry Bank](https://github.com/bitbank2) of [BitBank Software](https://www.bitbanksoftware.com). +The core GIF decoder is [GIF Animator](https://github.com/bitbank2/AnimatedGIF) by [Larry Bank](https://github.com/bitbank2) of [BitBank Software](https://www.bitbanksoftware.com). diff --git a/readme.md b/readme.md index 59340bd5b1..ba0104a44b 100755 --- a/readme.md +++ b/readme.md @@ -48,7 +48,7 @@ The Moddable SDK implements a variety of hardware protocols including digital (G ### Source level debugger -The `xsbug` JavaScript source level debugger is a full-featured debugger that supports debugging modules and applications for XS platforms. +The `xsbug` JavaScript source level debugger is a full-featured debugger that supports debugging modules and applications for XS platforms. Similar to other debuggers, `xsbug` supports setting breakpoints, browsing source code, and inspection of the call stack and variables. The `xsbug` debugger additionally provides real-time instrumentation to track memory usage and profile application and resource consumption. @@ -59,7 +59,7 @@ Similar to other debuggers, `xsbug` supports setting breakpoints, browsing sourc 1. To do anything with the Moddable SDK, you have to install it on your computer. This involves downloading this repository, installing some development tools, configuring settings over the command line, and building the Moddable SDK tools. The [Getting Started Guide](./documentation/Moddable%20SDK%20-%20Getting%20Started.md) in the `documentation` directory walks you through the whole process of installing the Moddable SDK. - + 2. With the Moddable SDK installed, you can build and run apps on hardware simulators. 3. To develop for a particular device, you need to install additional tools and SDKs for that device. The setup process for each device is different, but usually involves installing some additional SDKs, drivers, and development tools. @@ -162,7 +162,7 @@ The Moddable SDK supports four Gecko boards, shown below. | | | | | | :---: | :---: | :---: | :---: | -|
Giant Gecko |
Mighty Gecko |
Thunderboard Sense 2 |
Blue Gecko +|
Giant Gecko |
Mighty Gecko |
Thunderboard Sense 2 |
Blue Gecko ### QCA4020 by Qualcomm @@ -213,7 +213,7 @@ The Moddable SDK repository contains the following top level directories: The JavaScript APIs supported by the Moddable SDK are documented in a suite of documents in the [documentation](./documentation) directory. The documentation is an extensive reference, with numerous examples. The primary [Piu document](./documentation/piu/piu.md) alone is over 100 pages. All documentation is provided in markdown format. -See the [readme](./documentation#api-documentation-for-modules) document in that directory for an overview of the API documents. +See the [readme](./documentation#api-documentation-for-modules) document in that directory for an overview of the API documents. ## Resources @@ -244,7 +244,7 @@ If you're an independent developer, we recommend you [start a discussion](./disc To learn more about Moddable, see [our website](http://www.moddable.com). -For companies interested in the benefits of using JavaScript and the Moddable SDK to power your products, Moddable provides consulting services to help you get started. We're available to help with design, implementation, training, and support. +For companies interested in the benefits of using JavaScript and the Moddable SDK to power your products, Moddable provides consulting services to help you get started. We're available to help with design, implementation, training, and support. You can also reach out to us on Twitter ([@moddabletech](https://twitter.com/moddabletech)). Following us on Twitter is the best way to keep up with what we’re doing—we post announcements about new blog posts there, along with other Moddable news.