diff --git a/ble/README.md b/ble/README.md
index 5ce496c..ee996a9 100644
--- a/ble/README.md
+++ b/ble/README.md
@@ -154,10 +154,8 @@ The `startadvertising()` method runs the following steps:
##### The `stopAdvertising()` method
Requests the platform to stop sending advertisement packets. It runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
- Request from the underlying platform to stop the current advertisement.
-- If the request is unsuccessful, reject `promise` with an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothStopAdvertisement"`.
-- Otherwise, if the request was successful, resolve `promise`.
+- If the request is unsuccessful, throw an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothStopAdvertisement"`.
##### The `addService(service)` method
@@ -288,17 +286,13 @@ The `needsResponse` property is a boolean that is by default `true`.
##### The `respond(data)` method
Sends a response to the request. It executes the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
- Create a response to the request, and include `data` in the response.
- Request from the underlying platform to send the response to the client.
-- If the request is unsuccessful, reject `promise` with an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothSendResponse"`.
-- Otherwise, if the request was successful, resolve `promise`.
+- If the request is unsuccessful, throw an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothSendResponse"`.
##### The `error(error)` method
Sends an error response to the request. It executes the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
- Create an error response to the request, and include `error` in the response.
- Request from the underlying platform to send the response to the client.
-- If the request is unsuccessful, reject `promise` with an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothSendErrorResponse"`.
-- Otherwise, if the request was successful, resolve `promise`.
+- If the request is unsuccessful, throw an [`Error`](../README.md/#error) object `error` with `error.message` set to `"BluetoothSendErrorResponse"`.
diff --git a/ble/webidl.md b/ble/webidl.md
index 5c97f42..d9ba04b 100644
--- a/ble/webidl.md
+++ b/ble/webidl.md
@@ -19,7 +19,7 @@ interface BluetoothPeripheralDevice {
Promise startAdvertising(Advertisement advertisement,
optional AdvertisingOptions options);
- Promise stopAdvertising();
+ void stopAdvertising(); // Promise?
readonly attribute boolean enabled;
attribute EventHandler onenabledchange;
@@ -125,8 +125,8 @@ interface Request {
readonly attribute Buffer? data = null;
readonly attribute boolean needsResponse;
- Promise respond(optional Buffer data);
- Promise respondWithError(Error error);
+ void respond(optional Buffer data); // Promise?
+ void respondWithError(Error error); // Promise?
};
enum RequestType { "read", "write", "notify", "subscribe", "unsubscribe"};
diff --git a/board/README.md b/board/README.md
index 296f0ec..f670b30 100644
--- a/board/README.md
+++ b/board/README.md
@@ -9,133 +9,59 @@ The [Board](#board) API provides low level interfaces for I/O operations:
- [SPI - Serial Peripheral Interface](./spi.md)
- [UART - Universal Asynchronous Receiver/Transmitter](./uart.md).
-This API uses board pin names as defined in the corresponding board documentation.
-The names, values and semantics related to hardware pins are owned and encapsulated by the implementation. This API uses opaque values (strings and numbers) for [`Pin`](#pin) names.
+Hardware pin names are usually marked on the circuit boards, that defines a board namespace for pins. However, operating systems, such as Linux, or [Zephyr](https://www.zephyrproject.org/doc/) define a pin name mapping that is consistent across the boards supported by the OS. This API supports both board and OS (system) defined namespaces. Pin names are opaque to the application, either strings or numbers that gain meaning in either the board or OS namespace. Also, the API exposes board name, OS name (including OS version) and API version for all board APIs.
-The supported board documentations are listed in [this directory](./):
+Since it is generally easier for developers to just look at a given board and use the names printed there in the API, by default the board namespace is used, but developers can specify to use the system namespace as well. If a given pin value is not found in the default (or provided) namespace, an error is thrown: there is no fallback search in the other namespace.
+
+Examples for the supported board namespaces are listed in [this directory](./):
- [arduino101.md](./arduino101.md)
- [frdm_k64f.md](./frdm_k64f.md).
-The full Web IDL definition for Board and IO APIs can be found [here](./webidl.md).
+For the supported OS pin namespace, consult the documentation of the implementation and its underlying OS documentation.
+
+The full Web IDL definition for Board and IO APIs can be found in [webidl.md](./webidl.md).
The `Board` API object
----------------------
-The API entry point is a [`Board`](./#board) object that is exposed in a platform-specific manner. As an example, on Node.js it can be obtained by requiring the package that implements this API.
+The API entry point is a [`Board`](#board) object provided by an implementation (module).
+When requiring `"board"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the [Board](#board) functionality is not supported on the board, throw `"NotSupportedError"`.
+- Let `board` be the Board API object, and initialize it by fetching board name and OS name. Return `board`.
-In the following example, the application requires an implementation that exposed Arduino 101 values and semantics for pins.
```javascript
var board = require("board");
-console.log("Connected to board: " + board.name);
-```
-
-On other platforms, e.g. in browsers, the API entry point can be exposed on another object, or constructed.
-```javascript
-var board = new Board(); // provides an instance of the default board
+console.log("Connected to board: " + board.name + " running " + board.os);
```
-If the functionality is not supported by the platform, `require` should throw `NotSupportedError`. If there is no permission for using the functionality, `require` should throw `SecurityError`.
-
-
-### The `Pin` interface
-Represents a hardware pin on the board.
-
-| Property | Type | Optional | Default value | Represents |
-| --- | --- | --- | --- | --- |
-| `pin` | String or Number | no | `undefined` | board name for the pin |
-
-The read-only `pin` property is the board-specific name or numeric value of a pin, as defined in the board documentation.
-
-In future versions of the API the `Pin` object may be extended.
+If the functionality is not supported by the platform, `require` should throw `NotSupportedError`.
### The `Board` interface
-Represents a hardware board.
+Represents a hardware circuit board such as Arduino 101.
| Property | Type | Optional | Default value | Represents |
| --- | --- | --- | --- | --- |
-| [`name`](#name) | String | no | `undefined` | board name |
-| [`version`](#version) | String | no | `versions.board` in [`package.json`](../package.json) | API version |
-
-| Method signature | Description |
-| --- | --- |
-| [`aio()`](#aio) | request an AIO object |
-| [`gpio()`](#gpio) | request a GPIO object |
-| [`pwm()`](#pwm) | request a PWM object |
-| [`i2c()`](#i2c) | request an I2C object |
-| [`spi()`](#spi) | request an SPI object |
-| [`uart()`](#uart) | request an UART object |
+| [`name`](#boardname) | String | no | `undefined` | board name |
+| [`os`](#osname) | String | no | `undefined` | OS name |
+| [`apiVersion`](#apiversion) | String | no | `versions.board` in [`package.json`](../package.json) | API version |
| Event name | Event callback argument |
| -------------- | ----------------------- |
| `error` | [`Error`](#error) object |
-
+
The `name` property is read-only, and provides the board name.
-
-The `version` property is read-only, and provides the provides the Board API version, as specified in the `versions.board` property of [`package.json`](../package.json).
+
+The `os` property is read-only, and provides the underlying operating system name.
+
+
+The `apiVersion` property is read-only, and provides the provides the Board API version, as specified in the `versions.board` property of [`package.json`](../package.json).
Board errors are represented as augmented [`Error`](https://nodejs.org/api/errors.html#errors_class_error) objects. The following [`Error` names](https://nodejs.org/api/errors.html) are used for signaling issues:
- `BoardDisconnectError`
- `BoardTimeoutError`
- `BoardIOError`.
-
-#### `Board` methods
-
-
-##### The `aio(options)` method
-Configures an AIO pin. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the AIO functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the internal [`AIO initialization`](./aio.md/#init) algorithm with `options` as argument and let `aio` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `aio` object.
-
-
-##### The `gpio(options)` method
-Configures a GPIO pin or GPIO port. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the GPIO functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the internal [`GPIO initialization`](./gpio.md/#init) algorithm with `options` as argument and let `gpio` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `gpio` object.
-
-
-##### The `pwm(options)` method
-Configures a PWM pin. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the PWM functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the internal [`PWM initialization`](./pwm.md/#init) algorithm with `options` as argument and let `pwm` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `pwm` object.
-
-
-##### The `i2c(options)` method
-Configures I2C communication. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the I2C functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the internal [`I2C initialization`](./i2c.md/#init) algorithm with `options` as argument and let `i2c` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `i2c` object.
-
-
-##### The `spi(options)` method
-Configures SPI communication.
-The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the SPI functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the [`SPI init`](./spi.md/#init) steps with `options` as argument and let `spi` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `spi` object.
-
-
-##### The `uart(options)` method
-Configures UART communication. It takes a dictionary object as argument.
-The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If the UART functionality is not supported, reject `promise` with `"NotSupportedError"`.
-- Run the [`UART init`](./uart.md/#init) steps with `options` as argument and let `uart` be the returned result.
-- If it throws an error, reject promise with that error.
-- Resolve `promise` with the `uart` object.
diff --git a/board/aio.md b/board/aio.md
index e9b6de5..d3900e7 100644
--- a/board/aio.md
+++ b/board/aio.md
@@ -3,22 +3,47 @@ AIO API
The AIO API supports reading analog input pins that measure the analog voltage signal between 0 and a maximum voltage (usually 3.3 or 5 Volts), then do Analog-to-Digital Conversion (ADC) with a resolution of 10 or 12 bits on most boards, so that the result (pin value) is 0 to 1023 or 0 to 4095, inclusively.
-On some boards access to AIO may be asynchronous. This API uses synchronous read.
+On some boards access to AIO may be asynchronous. This API uses synchronous methods for allowing lean implementations.
-The API object
---------------
-AIO functionality is exposed by the [`AIO`](#aio) object that can be obtained by using the [`aio()`](./README.md/#aio) method of the [`Board` API](./README.md/#board). See also the [Web IDL](./webidl.md).
+
+### The AIO API object
+When requiring `"aio"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the AIO functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following method.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | open an AIO pin |
+
+See also the [Web IDL](./webidl.md) definition.
+
+
+#### The `AIO open(options)` method
+Configures an AIO pin using data provided by the `options` argument. It involves the following steps:
+- If `options` is a string, create a dictionary 'init' and use the value of `options` to initialize the `init.pin` property.
+- Otherwise if `options` is a number, create a dictionary 'init' and let `init.pin` be `options`.
+- Otherwise if `options` is a dictionary, let `init` be `options`. It may contain the following [`AIO`](#aio) properties, where at least `pin` MUST be specified:
+ * `pin` for board pin name with the valid values defined by the board, or for the numeric index of the analog pin;
+ * `mapping` to specify if OS or board namespace is to be used with the pin (by default `"board"`).
+ * `precision` for the bit width of a sample (if the board supports setting the sampling rate).
+- If any property of `init` is specified and has an invalid value, throw `TypeError`.
+- Request the underlying platform to initialize AIO on the pin identified by `init.pin` in the namespace specified by `init.mapping` if that is defined. If not found, throw `InvalidAccessError`. If `init.mapping is not defined, then search `init.pin` first in the OS namespace, then in board namespace. In case of failure, throw `InvalidAccessError`.
+- Let `aio` be the `AIOPin`](#aiopin) object that represents the hardware pin identified by `init.name`.
+- If `init.precision` is defined, request the board to set the precision and initialize the `aio.precision` property with the value supported by the underlying platform. If there is an error, throw `InvalidAccessError`.
+- Initialize the `aio.value` property with `undefined`.
+- Return the `aio` object.
### The `AIO` interface
-Represents the properties and methods that expose AIO functionality. The `AIO` object implements the [`EventEmitter`](../README.md/#events) interface, and extends the [`Pin`](./README.md/#pin) object. It has the following properties and methods:
| Property | Type | Optional | Default value | Represents |
| --- | --- | --- | --- | --- |
-| `pin` | String or Number | no | `undefined` | board name for the pin |
+| `pin` | String or Number | no | `undefined` | pin name |
+| `mapping` | enum | no | `"board"` | pin mapping, `"system"` or `"board"` |
| `precision` | unsigned long | yes | `undefined` | bit length of digital sample |
-| Method signature | Description |
+| Method | Description |
| --- | --- |
| [`read()`](#read) | synchronous read |
| [`close()`](#close) | close the pin |
@@ -27,52 +52,34 @@ The `pin` property inherited from [`Pin`](./README.md/#pin) can take values defi
The `precision` property represents the bit length of the digital sample. It is usually 10 or 12 bits, depending on board.
-
-#### AIO initialization
-This internal algorithm is used by the [`Board.aio()`](./README.md/#aio) method. Configures the AIO pin provided by the `options` argument. It involves the following steps:
-- If `options` is a string, create a dictionary 'init' and use the value of `options` to initialize the `init.pin` property.
-- Otherwise if `options` is a number, create a dictionary 'init' and use the value of `options` to initialize the `init.pin` property.
-- Otherwise if `options` is a dictionary, let `init` be `options`. It may contain the following [`AIO`](#aio) properties, where at least `pin` MUST be specified:
- * `pin` for board pin name with the valid values defined by the board, or for the numeric index of the analog pin;
- * `precision` for the bit width of a sample (if the board supports setting the sampling rate).
-- If any property of `init` is specified and has an invalid value on the given board, as defined by the board documentation, throw `TypeError`.
-- Request the underlying platform to initialize AIO on `init.pin` (if defined) or otherwise `init.channel`.
-- In case of failure, throw `InvalidAccessError`.
-- Let `aio` be the `AIO`](#aio) object that represents the hardware pin identified by `init.pin`, as defined by the board documentation.
-- If `init.precision` is defined, request the board to set the precision and initialize the `aio.precision` property with the value supported by the board. If there is an error, throw `InvalidAccessError`.
-- Initialize the `aio.value` property with `undefined`.
-- Return the `aio` object.
-
#### The `unsigned long read()` method
Performs a synchronous read operation for the pin value. It returns the pin value representing the last sampling.
#### The `close()` method
-Called when the application is no longer interested in the pin. Until the next [initialization](#init), invoking the `read()` method SHOULD throw `InvalidAccessError`.
+Called when the application is no longer interested in the pin. Until the next [open()](#open) is called, invoking the `read()` method throws `InvalidAccessError`.
### Examples
```javascript
-var board = require("board");
+try {
+ var aio = require("aio"); // initialize AIO on the board
-// Configure AIO using the board
-board.aio("A1").then(function(aio){
- // Read pin values.
- console.log(board.name + " AIO pin 1 value: " + aio.read());
+ var a1 = aio.open("A1"); // pin 1 in board namespace
+ console.log(board.name + " AIO pin 1 value: " + a1.read());
+ a1.close();
- // Release the pin.
- aio.close();
-});
+ // Open pin A4 in system namespace
+ var a4 = aio.open({pin: "ADC4", mapping: "system", precision: 12 });
-board.aio({pin: "A4", precision: 12 })
-.then(function(aio){ // read 10 samples, one every second
setTimeout(function() {
- aio.close();
+ a4.close();
}, 10500);
+
setInterval(function() {
- console.log("AIO pin 4 value: " + aio.read());
+ console.log("AIO pin 4 value: " + a4.read());
}, 1000);
-}).catch(function(err) {
- console.log("AIO error.");
-});
+} catch (err) {
+ console.log("AIO error: " + err.message);
+};
```
diff --git a/board/arduino101.md b/board/arduino101.md
index 271ce5f..e7e6ea4 100644
--- a/board/arduino101.md
+++ b/board/arduino101.md
@@ -1,7 +1,7 @@
Board Support for Arduino 101
=============================
-This document defines the pin values that are accepted by implementations.
+This document defines the pin values that are accepted by implementations on board namespace.
The board labels are described in the [Arduino 101](https://www.arduino.cc/en/Main/ArduinoBoard101) board documentation. Also, for each board pin, the supported modes of each pin is described.
diff --git a/board/frdm_k64f.md b/board/frdm_k64f.md
index a2d60bc..7f8aa14 100644
--- a/board/frdm_k64f.md
+++ b/board/frdm_k64f.md
@@ -1,6 +1,8 @@
Board Support for FRDM-K64F
===========================
+This document defines the pin values that are accepted by implementations on board namespace.
+
The FRDM-K64F board pin names and locations are shown [here](https://developer.mbed.org/platforms/FRDM-K64F/).
There are 16 general purpose I/O pins, `D0` - `D15`. `D14` and `D15` can currently be used as GPIO_INs but not as outputs.
diff --git a/board/gpio.md b/board/gpio.md
index 821f03d..ab33728 100644
--- a/board/gpio.md
+++ b/board/gpio.md
@@ -3,70 +3,97 @@ GPIO API
The GPIO (General Purpose Input & Output) API supports digital pins.
-The API object
---------------
-GPIO pin functionality is exposed by the [`GPIO`](#gpio) object that can be obtained by using the [gpio() method of the `Board` API](./README.md/#gpio). See also the [Web IDL](./webidl.md).
-
On certain boards GPIO pins may be grouped into ports (e.g. 8, 16 or 32 pins), read and written as registers by the controller.
On certain boards, analog pins can also be used as GPIO.
-
-### The `GPIO` interface
-Represents the properties and methods that expose GPIO functionality. The `GPIO` object implements the [`EventEmitter`](../README.md/#events) interface, and extends the [`Pin`](./README.md/#pin) object.
+
+### The GPIO API object
+When requiring `"gpio"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the GPIO functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following methods.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | open GPIO pin |
+| [`port()`](#port) | open GPIO port |
+
+See also the [Web IDL](./webidl.md) definition.
+
+The following dictionary is used for initializing GPIO pins and ports.
+
| Property | Type | Optional | Default value | Represents |
| --- | --- | --- | --- | --- |
-| `pin` | String or Number | no | `undefined` | board name for the pin |
+| `pin ` | String or Number | no | `undefined` | pin name |
+| `mapping` | String | no | `"board"` | pin mapping |
| `mode` | String | no | `undefined` | I/O mode |
-| `port` | array | yes | `undefined` | array of pin names representing the ports
| `activeLow` | boolean | yes | `false` | whether the pin is active on logical low |
| `edge` | string | yes | `"any"` | Interrupt generation mode |
| `state` | string | yes | `undefined` | "pulldown", "pullup" |
-| Method signature | Description |
-| --- | --- |
-| [`read()`](#read) | synchronous read |
-| [`write()`](#write) | synchronous write |
-| [`close()`](#close) | close the pin |
+The `pin` property is either a number or string, with values defined by the OS or board documentation. The default value is `undefined`.
-| Event name | Event callback argument |
-| -----------| ----------------------- |
-| `data` | unsigned long (the pin value) |
+The `mapping` property represents the pin namespace, either `"system"` or `"board"`, by default `"board"`.
-The `data` event listener callback receives the current value of the pin (0 or 1 for single pins, and positive integer for GPIO ports).
+The `mode` property MUST take the value `"in"` or `"out"`. The default value is `"out"`.
-The `pin` property inherited from [`Pin`](./README.md/#pin) can take values defined by the board documentation, usually positive integers.
+The `activeLow` property tells whether the pin value 0 means active. If `activeLow` is `true`, with `value` 0 the pin is active, otherwise inactive. For instance, if an actuator is attached to the (output) pin active on low, client code should write the value 0 to the pin in order to activate the actuator. The default value is `false`.
-The `mode` property MUST take the value `"input"` or `"output"`. The default value is `"input"`.
+The `edge` property is used for input pins and tells whether the `data` event is emitted on the rising edge of the signal (string value `"rising"`) when `value` changes from 0 to 1, or on falling edge (string value `"falling"`) when `value` changes from 1 to 0, or both edges (string value `"any"`), or never (string value `"none`"). The default value is `"none"`.
-The `port` property, if defined, is an array of strings that represents the ordered list of pin names that form a GPIO port, where the first element in the array represents the MSB.
+The `state` property tells if the internal pulldown (string value `"pulldown"`) or pullup (string value `"pullup"`) resistor is used for input pins to provide a default value (0 or 1) when the input is floating. The default value is `undefined`.
-The `activeLow` property tells whether the pin value 0 means active. If `activeLow` is `true`, with `value` 0 the pin is active, otherwise inactive. For instance, if an actuator is attached to the (output) pin active on low, client code should write the value 0 to the pin in order to activate the actuator.
-The `edge` property is used for input pins and tells whether the `data` event is emitted on the rising edge of the signal (string value `"rising"`) when `value` changes from 0 to 1, or on falling edge (string value `"falling"`) when `value` changes from 1 to 0, or both edges (string value `"any"`), or never (string value `"none`"). The default value is `"any"`, which means the event will fire on any change.
+
+#### The `GPIO open(options)` method
+Configures a GPIO pin using data provided by the `options` argument, that may contain the following properties:
+
+The method runs the following steps:
+- If `options` is a number or string, let `init` be a [GPIOOptions](#gpiooptions) object, let `init.pin` be `options` and let the other [GPIOOptions](#gpiooptions) properties take the default values.
+- If `options` is a dictionary and if `options.pin` is not defined, throw `TypeError`. If any of the `options` properties has an invalid value, throw `TypeError`. Let the the missing [GPIOOptions](#gpiooptions) properties take the default values. Let `init` be `options`.
+- Request the underlying platform to initialize GPIO on the pin identified by `init.pin` in the namespace specified by `init.mapping` if that is defined. If not found, throw `InvalidAccessError`. If `init.mapping is not defined, then search `init.pin` first in the OS namespace, then in board namespace. In case of failure, throw `InvalidAccessError`.
+- Let `gpio` be the [`GPIO`](#gpio) object that represents the requested pin corresponding to `init.pin` and return `gpio`.
+
+
+#### The `GPIO port(port, options)` method
+Configures a GPIO pin or port using data provided by the `options` argument that can take the same properties as in the [`open()`](#open) method.
+A GPIO port can be identified either by a symbolic name defined by the OS or the board, or a sequence of pin names the implementation binds together and are written and read together.
+The `port` argument is either a number or string representing a symbolic port name defined in the OS or board documentation, or an array of strings representing the pin names participating in the port in MSB order, i.e. the first element in the array represents the MSB.
+
+The `port()` method runs the following steps:
+- If `options` is a defined, let `mapping` be `init.mapping`. Let `init` be `options` and let the the missing [GPIOOptions](#gpiooptions) properties take the default values.
+- Otherwise if `options` is not defined, let `init` be a [GPIOOptions](#gpiooptions) dictionary with all properties taking the default value.
+- If `port` is a number or string, run the following sub-steps:
+ * If `mapping` is defined, match `port` to the supported GPIO port names in the pin namespace specified by `mapping`. If not found, throw `InvalidAccessError`.
+ * Otherwise if `mapping` is not defined, search `port` first in the OS namespace, then in board namespace. If both fail, throw `InvalidAccessError`.
+ * Request the underlying platform to initialize the GPIO port identified by `port` and initialize it using `init`.
+ * Let `gpio` be the [`GPIO`](#gpio) object representing the requested port and return `gpio`.
+- Otherwise if `init.port` is an array, run the following sub-steps for aggregating pins in the implementation:
+ * Let `gpio` be a [`GPIO`](#gpio) object.
+ * For each pin name in the `port` sequence, run the [`open()`](#open) method with `init` as argument, associate the returned [`GPIO`](#gpio) object with the `gpio` object and make it represent a bit in the value returned by `gpio.read()`, with the first element in the sequence representing the most significant bit. If any of the opens fail, close the other pins and throw `InvalidAccessError`.
+ * Initialize [`gpio.write()`](#write) with a function that obtains the corresponding bit values for each pin participating in the port and writes the pin values. Re-throw any errors.
+ * Initialize [`gpio.read()`](#read) with a function that reads the corresponding bit values from each pin participating in the port and returns the assembled value. Re-throw any errors.
+ * Initialize [`gpio.close()`](#close) with a function that closes each participating pin. Re-throw any errors.
+ * For any listener on the `data` event, on notification from the underlying platform on a value change on any participating pin, implementations SHOULD wait a platform-dependent short time and then fire the `data` event with the value assembled from the participating pins.
+ * Return the `gpio` object.
-The `state` property tells if the internal pulldown (string value `"pulldown"`) or pullup (string value `"pullup"`) resistor is used for input pins to provide a default value (0 or 1) when the input is floating. The default value is `undefined`.
+
+### The `GPIO` interface
+The `GPIO` interface implements the [`EventEmitter`](../README.md/#events) interface. It exposes the following methods and event.
-
-#### GPIO initialization
-This internal algorithm is used by the [`Board.gpio()`](./README.md/#gpio) method. Configures the GPIO pin or GPIO port provided by the `options` argument.
-- If `options` is a number or string, create a dictionary `init` and use the value of `options` to initialize the `init.pin` property.
-- Otherwise if `options` is a dictionary, let `init` be `options`. It may contain the following [`GPIO`](#gpio) properties:
- * `pin` for the GPIO pin or port name defined by the board
- * `port` for the array of GPIO pins that define the port
- * `mode` with valid values `"input"` or `"output"`, by default `"input"`
- * `activeLow`, by default `false`
- * `edge`, by default `"any"`
- * `state`, by default `undefined`.
-- If any of the `init` properties has an invalid value, throw `TypeError`.
-- If `init.port` is defined and matches a GPIO port name defined by the board, run the following sub-steps:
- * request the underlying platform to initialize the GPIO port on the given board with the `init` properties. In case of failure, throw `InvalidAccessError`.
- * Let `gpio` be the [`GPIO`](#gpio) object representing the requested port initialized by `init`.
-- Otherwise, if `init.pin` is defined, run the following sub-steps:
- * Let `gpio` be the [`GPIO`](#gpio) object representing the requested pin initialized by `init`. For the [`GPIO`](#gpio) properties missing from the `init` dictionary, use the default values of the `GPIO` object properties.
- * Initialize the `gpio.pin` property with `init.pin`.
-- Return the `gpio` object.
+| Method | Description |
+| --- | --- |
+| [`read()`](#read) | synchronous read |
+| [`write()`](#write) | synchronous write |
+| [`close()`](#close) | close the pin |
+
+| Event name | Event callback argument |
+| -----------| ----------------------- |
+| `data` | unsigned long (the pin value) |
+
+The `data` event listener callback receives the current value of the pin (0 or 1 for single pins, and positive integer for GPIO ports). Implementations SHOULD use a platform-dependent minimum time interval between firing two consecutive events.
#### The `unsigned long read()` method
@@ -78,68 +105,66 @@ If `value` is `0`, `null` or `undefined`, let `value` be 0. Otherwise, if `port`
#### The `close()` method
-Called when the application is no longer interested in the pin. This also removes all listeners to the `data` event. Until the next invocation of `init()`, invoking the `write()` method or reading the `value` property SHOULD throw `InvalidAccessError`.
+Called when the application is no longer interested in the pin. This also removes all listeners to the `data` event. Until the next invocation of [`open()`](#open), invoking the `write()` method or reading the `value` property SHOULD throw `InvalidAccessError`.
### Examples
#### Working with GPIO pins
```javascript
-var board = require("board");
-
-var gpio3 = board.gpio(3) // GPIO input pin with default configuration.
- .then(function(gpio){
- console.log(board.name + " GPIO pin 3 value: " + gpio3.read());
- gpio3.close();
- });
-
-board.gpio({ pin: 5, mode: "output", activeLow: true })
- .then(function(gpio) {
- gpio.write(0); // activate pin
- gpio.close();
- });
-
-board.gpio({pin: 6, edge: "any"})
- .then(function(gpio) {
- gpio.on("data", function(value) {
- console.log("GPIO pin 6 has changed; value: " + value);
- };
-
- setTimeout(function(){
- gpio.close();
- }, 2000);
-
- }).catch (function(err) {
- console.log("GPIO error.");
- });
+try {
+ var board = require("board");
+ var gpio = require("gpio");
+
+ var gpio3 = gpio.open(3); // GPIO input pin with default configuration.
+ gpio3.write(1); // activate pin
+ gpio3.close();
+
+ var gpio5 = gpio.open({ pin: 5, mode: "out", activeLow: true });
+ gpio5.write(0); // activate pin
+ gpio5.close();
+
+ gpio6 = gpio.open({ pin: 6, mode: "in", edge: "any"});
+ gpio6.on("data", function(value) {
+ console.log("GPIO pin 6 has changed; value: " + value);
+ });
+ setTimeout(function(){
+ gpio6.close();
+ }, 2000);
+
+} catch (err) {
+ console.log("GPIO error: " + err.message);
+};
```
#### Working with GPIO ports
```javascript
-var board = require("board");
-
-// Configure a GPIO port using default configuration
-board.gpio({ port: [3,4,5,6,7,8]})
- .then(function(gpio){
- // Set up a change listener on the port value.
- gpio.on("data", function(value) {
- console.log("GPIO port value has changed; value: " + gpio.read());
- });
-
- setTimeout(function(){
- gpio.close();
- }, 2000);
-
- });
-
-// Initialize and write an output port
-board.gpio({ port: [5,6,7,8], mode: "output", activeLow: true })
-.then(function(gpio){
- gpio.write(0x21);
- gpio.close();
-}).catch(function(error){
- console.log("GPIO error: " + error.message);
-});
-
+try {
+ var gpio = require("gpio");
+ // Configure a GPIO port using default configuration
+ var gport1 = gpio.port([3,4,5,6,7,8], { mode: "in"});
+
+ // Set up a change listener on the port value.
+ gport1.on("data", function(value) {
+ console.log("GPIO port value has changed; value: " + gport1.read());
+ });
+
+ setTimeout(function(){
+ gport1.close();
+ }, 2000);
+
+ // Initialize and write an output port
+ var gport2 = gpio.port([5,6,7,8], { activeLow: true });
+ gport2.write(0x21);
+ gport2.close();
+
+ // Configure a GPIO port supported in the platform under a symbolic name
+ var gport3 = gpio.port("gpio-port-1", { activeLow: true });
+ gport3.write(0x21);
+ gport3.close();
+
+} catch (err) {
+ console.log("GPIO port error: " + error.message);
+};
```
diff --git a/board/i2c.md b/board/i2c.md
index 23331b8..bfbdfdb 100644
--- a/board/i2c.md
+++ b/board/i2c.md
@@ -11,9 +11,28 @@ If write was requested, the master puts the bit on SDA and sends a clock signal
Therefore it is important to select the right speed supported by the master and slave devices.
This API uses a [`Buffer`](../README.md/#buffer) object for both read and write.
-The API object
---------------
-I2C functionality is exposed by the [`I2C`](#i2c) object that can be obtained by using the [i2c() method of the `Board` API](./README.md/#i2c). See also the [Web IDL](./webidl.md).
+
+### The I2C API object
+When requiring `"i2c"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the I2C functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following method.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | synchronous open |
+
+See also the [Web IDL](./webidl.md) definition.
+
+
+#### The `I2C open(options)` method
+Configures an I2C bus using data provided by the `options` argument. It runs the following steps:
+- Let `i2c` be an `I2C`](#i2c) object.
+- If `options` is a dictionary and the `options.bus` property is a number between 0 and 127, let `i2c.bus` be `options.bus`, otherwise select the platform default value, and if that is not available, set the value to 0.
+- If `options.speed` is not a number, let `i2c.speed` be 10. Otherwise, if it is in the { 10, 100, 400, 1000, 3400 } set, let `i2c.speed` take that value, otherwise set `i2c.speed` to the closest matching value.
+- Request the underlying platform to initialize the I2C `bus` with `i2c.speed` on `board`.
+- In case of failure, throw `InvalidAccessError`.
+- Return `i2c`.
### The `I2C` interface
@@ -24,68 +43,48 @@ Represents the properties and methods that expose I2C functionality.
| `bus` | octet | yes | platform selected | I2C bus |
| `speed` | long | yes | platform selected | I2C bus speed |
-| Method signature | Description |
-| --- | --- |
-| [`write(device, buffer)`](#write) | write data to a device |
-| [`read(device, size)`](#read) | read data from a device |
-| [`close()`](#close) | close the I2C bus |
+| Method | Description |
+| --- | --- |
+| [`write()`](#write) | write data to a device |
+| [`read()`](#read) | read data from a device |
+| [`close()`](#close) | close the I2C bus |
The `bus` property denotes the I2C bus number between 0 and 127.
The `speed` property can take the following numeric values denoting kilobits per second: 10, 100, 400, 1000, 3400.
-
-#### I2C initialization
-This internal algorithm is used by the [`Board.i2c()`](./README.md/#i2c) method. Configures the I2C bus and bus speed provided by the `options` (first) dictionary argument on the [`board`](./README.md/#board) specified by the `board` (second) argument.
-- Let `i2c` be an `I2C`](#i2c) object.
-- If `options` is a dictionary and the `options.bus` property is a number between 0 and 127, let `i2c.bus` be `options.bus`, otherwise select the platform default value, and if that is not available, set the value to 0.
-- If `options.speed` is not a number, let `i2c.speed` be 10. Otherwise, if it is in the { 10, 100, 400, 1000, 3400 } set, let `i2c.speed` take that value, otherwise set `i2c.speed` to the closest matching value.
-- Request the underlying platform to initialize the I2C `bus` with `i2c.speed` on `board`.
-- In case of failure, return `null`.
-- Return `i2c`.
-
#### The `write(device, buffer)` method
Writes a [`Buffer`](../README.md/#buffer) using I2C to slave `device`. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If `device` is not a number between 0 and 127, reject `promise` with `TypeError` and terminate these steps.
-- Create a [`Buffer`](../README.md/#buffer) from `buffer`. If that fails, reject `promise` with `TypeError` and terminate these steps.
-- Request the underlying platform to write the specified bytes to the specified device.
-If the operation fails, reject `promise`.
-- Otherwise, resolve `promise`.
+- If `device` is not a number between 0 and 127, throw `TypeError` and terminate these steps.
+- Request the underlying platform to write the bytes specified by `buffer` argument to the specified device. If the operation fails, throw `SystemError`.
#### The `read(device, size)` method
-Reads maximum `size` number of bytes from I2C device `device` and resolves with a [`Buffer`](../README.md/#buffer). The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If `device` is not a number between 0 and 127, reject `promise` with `TypeError` and terminate these steps.
-- Create a [`Buffer`](../README.md/#buffer) from `buffer`.
-- Request the underlying platform to read `size` number of bytes from the specified `device` into `buffer`.
-If the operation fails, reject `promise`.
-- Otherwise, resolve `promise` with `buffer`.
+Reads maximum `size` number of bytes from I2C device `device` and returs a [`Buffer`](../README.md/#buffer). The method runs the following steps:
+- If `device` is not a number between 0 and 127, throw `TypeError` and terminate these steps.
+- Allocate a [`Buffer`](../README.md/#buffer).
+- Request the underlying platform to read `size` number of bytes from the specified `device` into `buffer`. If the operation fails, throw `SystemError`.
+- Return `buffer`.
#### The `close()` method
-Closes the current [`I2C`](#i2c) bus and interrupts all pending operations.
+Closes the current [`I2C`](#i2c) bus and cancels all pending operations.
### Examples
```javascript
try {
- var board = require("board");
- var i2c = null;
-
- board.i2c().then(function(iic) {
- i2c = iic;
- console.log("I2C bus " + i2c.bus + " opened with bus speed " + i2c.speed);
- return i2c.write(0x02, [1, 2, 3]);
- }).then(function() {
- return i2c.read(0x03, 3);
- }).then(function(buffer) {
- console.log("From I2C device 0x03: " + buffer.toString());
- i2c.close();
- }).catch(function(err) {
- console.log("I2C error: " + err.message);
- });
+ var i2c = require("i2c").open(); // open the default I2C bus
+ console.log("I2C bus " + i2c.bus + " opened with bus speed " + i2c.speed);
+
+ i2c.write(0x02, [1, 2, 3]);
+
+ var buffer = i2c.read(0x03, 3);
+ console.log("From I2C device 0x03: " + buffer.toString());
+
+ i2c.close();
+} catch (err) {
+ console.log("I2C error: " + err.message);
}
```
diff --git a/board/pwm.md b/board/pwm.md
index 26b7052..e1c4c1d 100644
--- a/board/pwm.md
+++ b/board/pwm.md
@@ -6,46 +6,60 @@ The PWM API supports writing analog values to pins using Pulse Width Modulation.
PWM is characterized by a repeating digital signal of given pulse width (duration for value 1 in normal polarity and for value 0 in reverse polarity) and a total duration of the signal (period). Also, PWM is characterized by a duty cycle that is the ratio between the pulse width and the total signal period.
For instance, a LED that is driven with a PWM signal with 50% duty cycle will be approximately half-bright.
-The term "channel" is used as the numeric index of a PWM pin relative to the PWM controller, as described in the board documentation.
+The term "channel" is used as the numeric index of a PWM pin relative to the PWM controller starting with 1.
-The API object
---------------
-PWM functionality is exposed by the [`PWM`](#pwm) object that can be obtained by using the [pwm() method of the `Board` API](./README.md/#pwm). See also the [Web IDL](./webidl.md).
+
+### The PWM API object
+When requiring `"pwm"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the PWM functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following method.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | open a PWM pin |
+
+See also the [Web IDL](./webidl.md) definition.
+
+
+#### The `PWM open(options)` method
+Configures a PWM pin using data provided by the `options` argument. It runs the following steps:
+- If `options` is a string or number, create a dictionary `init` and use the value of `options` to initialize the `init.pin` property.
+- Otherwise if `options` is a dictionary, let `init` be `options`. It may contain the following [`PWM`](#pwm) properties, but at least `name`
+ * `pin` for pin name
+ * `mapping` for pin mapping, either `"system"` or `"board"`, by default `"board"`
+ * `reversePolarity`, by default `false`.
+- If any of the `init` properties is specified, but has invalid value on the board, throw `InvalidAccessError`.
+- Let `mapping` be `init.mapping`.
+- Let the missing `init` properties take the default value.
+- Request the underlying platform to initialize PWM on the pin identified by `init.pin` in the namespace specified by `mapping` if that is defined. If not found, throw `InvalidAccessError`. If `mapping is not defined, then search `init.pin` first in the OS namespace, then in board namespace. In case of failure, throw `InvalidAccessError`.
+- Let `pwm` be the [`PWM`](#pwm) object representing the pin identified by the `init.pin` initialized by `init`.
+- Return the `pwm` object.
### The `PWM` interface
-Represents the properties and methods that expose PWM functionality. The `PWM` object extends the [`Pin`](./README.md/#pin) object.
+Represents the properties and methods that expose PWM functionality.
| Property | Type | Optional | Default value | Represents |
| --- | --- | --- | --- | --- |
-| `pin` | String or Number | no | `undefined` | board name for the pin, or channel number |
+| `pin` | String or Number | no | `undefined` | pin name |
+| `mapping` | String | no | `"board"` | pin mapping |
| `reversePolarity` | boolean | yes | `false` | PWM polarity |
| `write()` | function | no | defined by implementation | set and enable PWM signal |
| `stop()` | function | no | defined by implementation | stop the PWM signal |
| `close()` | function | no | defined by implementation | release the pin |
-| Method signature | Description |
+| Method | Description |
| --- | --- |
-| [`write(value)`](#write) | set and start a PWM signal |
+| [`write()`](#write) | set and start a PWM signal |
| [`stop()`](#stop) | stop the PWM signal |
| [`close()`](#close) | close the pin |
-The `pin` property inherited from [`Pin`](./README.md/#pin) can take values defined by the board documentation, either a pin name, or a channel number.
+The `pin` property is an opaque number or string, representing a pin name.
-The `reversePolarity` property tells whether the PWM signal is active on 0. The default value is `false`.
+The `mapping` property represents the pin namespace, either `"board"` or `"system"`.
-
-#### PWM initialization
-This internal algorithm is used by the [`Board.pwm()`](./README.md/#pwm) method. Configures the PWM pin provided by the `options` argument. It runs the following steps:
-- If `options` is a string or number, create a dictionary `init` and use the value of `options` to initialize the `init.pin` property.
-- Otherwise if `options` is a dictionary, let `init` be `options`. It may contain the following [`PWM`](#pwm) properties, but at least `pin`
- * `pin` for board pin name, or PWM channel number, as defined by the board documentation
- * `reversePolarity`, with a default value `false`.
-- If any of the `init` properties is specified, but has invalid value on the board, throw `InvalidAccessError`.
-- Let `pwm` be the [`PWM`](#pwm) object representing the pin identified by the `init.pin` and request the underlying platform to initialize PWM for the given pin. In case of failure, throw `InvalidAccessError`.
-- Initialize the `pwm.pin` property with `init.pin`.
-- Initialize the `pwm.reversePolarity` property with `init.reversePolarity`.
-- Return the `pwm` object.
+The `reversePolarity` property tells whether the PWM signal is active on 0. The default value is `false`.
#### The `write(value)` method
@@ -78,18 +92,18 @@ Called when the application is no longer interested in the pin. It invokes the `
### Examples
```javascript
-var board = require("board");
-
-board.pwm(6) // configure pin 6 as PWM
- .then(function(pwm){
- pwm.write({ period: 2.5, pulseWidth: 1.5 }); // duty cycle is 60%
- console.log("PWM duty cycle: " + pwm.dutyCycle);
- setTimeout(function(){
- pwm.stop(); // stop the PWM signal
- pwm.close();
- }, 2000);
- }).catch(function(error) {
- console.log("PWM error: " + error.message);
- });
+try {
+ var pwm = require("pwm");
+
+ var pwm6 = pwm.open(6); // configure pin 6 as PWM
+ pwm6.write({ period: 2.5, pulseWidth: 1.5 }); // duty cycle is 60%
+ console.log("PWM duty cycle: " + pwm6.dutyCycle);
+ setTimeout(function(){
+ pwm6.stop(); // stop the PWM signal
+ pwm6.close();
+ }, 2000);
+}.catch (error) {
+ console.log("PWM error: " + error.message);
+};
```
diff --git a/board/spi.md b/board/spi.md
index f99a868..494dbec 100644
--- a/board/spi.md
+++ b/board/spi.md
@@ -11,9 +11,34 @@ Since the SS pins may be connected to slave chip select through a demultiplexer
This API uses a [`Buffer`](../README.md/#buffer) object for both read and write data.
-The API object
---------------
-SPI functionality is exposed by the [`SPI`](#spi) object that can be obtained by using the [spi() method of the `Board` API](./README.md/#spi). See also the [Web IDL](./webidl.md).
+
+### The SPI API object
+When requiring `"spi"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the SPI functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following method.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | synchronous open |
+
+See also the [Web IDL](./webidl.md) definition.
+
+
+#### The `SPI open(options)` method
+Configures an SPI bus using data provided by the `options` argument. It runs the following steps:
+- Let `spi` be an [`SPI`](#spi) object.
+- If `options` is a dictionary and the `options.bus` property is a number between 0 and 127, let `spi.bus` be `options.bus`, otherwise select the platform default value, and if that is not available, set the value to 0.
+- If `options.speed` is not a number, let `spi.speed` be 10. Otherwise, set `spi.speed` to the closest matching value that is lower than `options.speed` and is supported by the platform.
+- If `options.msbFirst` is `false`, set `spi.msbFirst` to `false`, otherwise set it to `true`.
+- If `options.bits` is in the set {1, 2, 4, 8, 16 }, then set `spi.bits` to `option.bits`, otherwise set it to the value 4.
+- If `options.polarity` is 0, then set `spi.polarity` to 0, otherwise set `spi.polarity` to 2.
+- If `options.phase` is 0, then set `spi.phase` to 0, otherwise set `spi.phase` to 1.
+- Request the underlying platform to initialize the SPI `spi.bus` with `spi.speed` on the board. The implementation will use the board mapping from the value of `bus` to the set of physical pins used for the bus.
+- In case of failure in any of the steps above, return `null`.
+- Set `spi.frameGap` to 0. Request the underlying platform to provide the SPI inter-frame delay value expressed in nanoseconds and if the request successfully completes, then set `spi.frameGap` to that value.
+- Set `spi.topology` to `"full-duplex"`. Request the underlying platform to provide the SPI transfer mode and if the request successfully completes, then set `spi.topology` to the corresponding value.
+- Return `spi`.
### The `SPI` interface
@@ -64,58 +89,35 @@ The `topology` property describes the SPI master-slave connection type. This val
- `"multiplexed"`: 4 SS lines are connected to a decoder that can activate up to 15 slave devices. This works as full-duplex.
- `"daisy-chain"`: the master uses one SS and one SCLK (clock) line for all slaves. The MOSI line from the master goes to the first slave's MOSI pin, the MISO line of that slave goes to the MOSI pin of the next slave, and so forth. The last slave's MISO line is connected to the master's MISO pin.
-
-#### SPI initialization
-This internal algorithm is used by the [`Board.spi()`](./README.md/#spi) method. It configures the SPI bus and bus speed provided by the `options` dictionary argument.
-- Let `spi` be an [`SPI`](#spi) object.
-- If `options` is a dictionary and the `options.bus` property is a number between 0 and 127, let `spi.bus` be `options.bus`, otherwise select the platform default value, and if that is not available, set the value to 0.
-- If `options.speed` is not a number, let `spi.speed` be 10. Otherwise, set `spi.speed` to the closest matching value that is lower than `options.speed` and is supported by the platform.
-- If `options.msbFirst` is `false`, set `spi.msbFirst` to `false`, otherwise set it to `true`.
-- If `options.bits` is in the set {1, 2, 4, 8, 16 }, then set `spi.bits` to `option.bits`, otherwise set it to the value 4.
-- If `options.polarity` is 0, then set `spi.polarity` to 0, otherwise set `spi.polarity` to 2.
-- If `options.phase` is 0, then set `spi.phase` to 0, otherwise set `spi.phase` to 1.
-- Request the underlying platform to initialize the SPI `spi.bus` with `spi.speed` on the board. The implementation will use the board mapping from the value of `bus` to the set of physical pins used for the bus.
-- In case of failure in any of the steps above, return `null`.
-- Set `spi.frameGap` to 0. Request the underlying platform to provide the SPI inter-frame delay value expressed in nanoseconds and if the request successfully completes, then set `spi.frameGap` to that value.
-- Set `spi.topology` to `"full-duplex"`. Request the underlying platform to provide the SPI transfer mode and if the request successfully completes, then set `spi.topology` to the corresponding value.
-- Return `spi`.
-
#### The `transceive(device, buffer)` method
Writes a [`Buffer`](../README.md/#buffer) `buffer` using SPI to the slave identified by the `device` argument, and reads another [`Buffer`](../README.md/#buffer) from the slave device that is returned. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- If `device` is not a number between 0 and 127, reject `promise` with `TypeError` and terminate these steps.
-- Create a [`Buffer`](../README.md/#buffer) from `buffer` (may be empty). If that fails, reject `promise` with `TypeError` and terminate these steps.
-- Request the underlying platform to write the specified `buffer` to the specified device and read another [`Buffer`](../README.md/#buffer) `readBuffer`. The implementation maps the value of `device` to the physical SS (slave select) pins on the board.
-If the operation fails, reject `promise`.
-- Otherwise, resolve `promise` with `readBuffer`.
+- If `device` is not a number between 0 and 127, Throw `TypeError` and terminate these steps.
+- Request the underlying platform to write the bytes specified in `buffer` to the specified device and read another [`Buffer`](../README.md/#buffer) `readBuffer`. The implementation maps the value of `device` to the physical SS (slave select) pins on the board. If the operation fails, throw `SystemError` and abort these steps.
+- Return `readBuffer`.
#### The `close()` method
-Closes the current [`SPI`](#spi) bus and interrupts all pending operations.
+Closes the current [`SPI`](#spi) bus and cancels all pending operations.
### Examples
```javascript
try {
- var board = require("board");
-
- board.spi().then(function(spi) {
- console.log("SPI bus " + spi.bus + " opened with bus speed " + spi.speed);
- console.log("SPI mode: " + spi.mode);
- console.log("Data bits: " + spi.bits);
- console.log("Speed [MHz]: " + spi.speed);
- console.log("MSB first: " + (spi.msbFirst ? "true" : "false"));
-
- spi.transceive(0, [1, 2, 3]).then(function(buffer) {
- // Buffer object
- console.log("From SPI device 0: " + buffer.toString());
- spi.close();
- });
- });
- }).catch(function(err) {
- console.log("SPI error: " + err.message);
- });
+ var spi = require("spi").open(); // open the default SPI bus
+
+ console.log("SPI bus " + spi.bus + " opened with bus speed " + spi.speed);
+ console.log("SPI mode: " + spi.mode);
+ console.log("Data bits: " + spi.bits);
+ console.log("Speed [MHz]: " + spi.speed);
+ console.log("MSB first: " + (spi.msbFirst ? "true" : "false"));
+
+ var buffer = spi.transceive(0, [1, 2, 3]);
+ console.log("From SPI device 0: " + buffer.toString());
+
+ spi.close();
+} catch (err) {
+ console.log("SPI error: " + err.message);
}
```
diff --git a/board/uart.md b/board/uart.md
index 20fb8f4..de5f36f 100644
--- a/board/uart.md
+++ b/board/uart.md
@@ -4,17 +4,36 @@ UART API
The UART API supports the Universal Asynchronous Receiver/Transmitter that allows the board to communicate with other external devices. It uses 2 pins, RX for receiving and TX for transmitting. UART ports are usually referred by string names, but numbers may also be accepted, as defined in the board documentation.
This API uses a [`Buffer`](../README.md/#buffer) object for both read and write.
-The API object
---------------
-UART functionality is exposed by the [`UART`](#uart) object that can be obtained by using the [uart() method of the `Board` API](./README.md/#uart). See also the [Web IDL](./webidl.md).
+
+### The UART API object
+When requiring `"uart"`, the following steps are run:
+- If there is no permission for using the functionality, throw `SecurityError`.
+- If the UART functionality is not supported on the board, throw `"NotSupportedError"`.
+- Return an object that implements the following method.
+
+| Method | Description |
+| --- | --- |
+| [`open()`](#open) | synchronous open |
+
+See also the [Web IDL](./webidl.md) definition.
+
+
+#### The `UART open(options)` method
+Configures an UART port using data provided by the `options` argument. It runs the following steps:
+- Let `uart` be an [`UART`](#uart) object.
+- For all `uart` properties, if the `options` dictionary defines the same property with a valid value, let the `uart` property take that value, otherwise the default value.
+- Request the underlying platform to initialize the UART with the parameters provided by `uart`.
+- In case of failure, throw `SystemError` and abort these steps.
+- Invoke the `uart.setReadRange(min, max)` method with `min` = 1, and `max` taking a value determined by the platform that is greater than or equal to 1.
+- Return `uart`.
### The `UART` interface
-Represents the properties and methods that expose UART functionality. The `UART` interface implements the [`EventEmitter`](../README.md/#events) interface and exposes one event.
+Represents the properties, methods and event that expose UART functionality. The `UART` interface implements the [`EventEmitter`](../README.md/#events) interface.
| Event name | Event callback argument |
| -------------- | ----------------------- |
-| `data` | [`Buffer`](../README.md/#buffer) |
+| `read` | [`Buffer`](../README.md/#buffer) |
| Property | Type | Optional | Default value | Represents |
| --- | --- | --- | --- | --- |
@@ -25,10 +44,10 @@ Represents the properties and methods that expose UART functionality. The `UART`
| `parity` | enum | yes | `'none'` | `'none'`, `'even'`, `'odd'` |
| `flowControl` | boolean | yes | `false` | if flow control is on |
-| Method signature | Description |
+| Method | Description |
| --- | --- |
-| [`write(buffer)`](#write) | write a buffer |
-| [`setReadRange(min, max)`](#readrange) | set buffer sizes for read notifications |
+| [`write()`](#write) | write a buffer |
+| [`setReadRange()`](#readrange) | set buffer sizes for read notifications |
| [`close()`](#close) | close the UART port |
The `port` property denotes the UART port as a string defined by the board documentation, such as `"tty0"`, `"serialUSB0"`, etc.
@@ -43,29 +62,14 @@ The `parity` property can take the following values: `"none"` (by default), `"ev
The `flowControl` boolean property denotes if flow control is used. By default it is `false`.
-
-#### UART initialization
-This internal algorithm is used by the [`Board.uart()`](./README.md/#uart) method. Configures UART with the `options` dictionary argument.
-- If `options.port` is not a string, return `null`.
-- Let `uart` be an [`UART`](#uart) object.
-- For all `uart` properties, if the `options` dictionary defines the same property with a valid value, let the `uart` property take that value, otherwise the default value.
-- Request the underlying platform to initialize the UART with the parameters provided by `uart`.
-- In case of failure, return `null`.
-- Invoke the `uart.setReadRange(min, max)` method with `min` = 1, and `max` taking a value determined by the platform that is greater than or equal to 1.
-- Return `uart`.
-
#### The `write(buffer)` method
Transmits a [`Buffer`](../README.md/#buffer) using UART. The method runs the following steps:
-- Return a [`Promise`](../README.md/#promise) object `promise` and continue [in parallel](https://html.spec.whatwg.org/#in-parallel).
-- Create a [`Buffer`](../README.md/#buffer) from `buffer`. If that fails, reject `promise` with `TypeError` and terminate these steps.
-- Request the underlying platform to send the specified bytes.
-If the operation fails, reject `promise`.
-- Otherwise, resolve `promise`.
+- Request the underlying platform to send the bytes specified in `buffer`. If the operation fails, throw `SystemError` and abort these steps.
#### The `setReadRange(min, max)` method
-Sets the minimum and maximum number of bytes for triggering the `onread` event. Whenever at least `min` number of bytes is available, a [`Buffer`](../README.md/#buffer) object containing a `max` number of bytes is sent with the `onread` event.
+Sets the minimum and maximum number of bytes for triggering the `onread` event. Whenever at least `min` number of bytes is available, the `read` event is fired with a [`Buffer`](../README.md/#buffer) containing at maximum `max` number of bytes.
#### The `close()` method
@@ -75,26 +79,24 @@ Closes the current [`UART`](#uart) port and interrupts all pending operations.
```javascript
try {
- var board = require("board");
+ var uart = require("uart").open("serialUSB0");
- board.uart("serialUSB0").then(function(uart) {
- console.log("UART port " + uart.port);
- console.log("Speed [bps]: " + uart.speed);
- console.log("Data bits: " + uart.dataBits);
- console.log("Stop bits: " + uart.stopBits);
- console.log("Parity: " + uart.parity);
- console.log("Flow control " + (uart.flowControl ? "on." : "off.");
+ console.log("UART port " + uart.port);
+ console.log("Speed [bps]: " + uart.speed);
+ console.log("Data bits: " + uart.dataBits);
+ console.log("Stop bits: " + uart.stopBits);
+ console.log("Parity: " + uart.parity);
+ console.log("Flow control " + (uart.flowControl ? "on." : "off.");
- uart.setReadRange(8, 16); // min 8 byes, max 16 bytes in one read event
+ uart.setReadRange(8, 16); // min 8 byes, max 16 bytes in one read event
- uart.on("read", function(buffer) {
- console.log("UART received: " + buffer.toString());
- });
+ uart.on("read", function(buffer) {
+ console.log("UART received: " + buffer.toString());
+ });
- uart.write([1, 2, 3]);
+ uart.write([1, 2, 3]);
- }).catch(function(err) {
- console.log("UART error: " + err.message);
- });
+} catch(err) {
+ console.log("UART error: " + err.message);
}
```
diff --git a/board/webidl.md b/board/webidl.md
index 682e133..f6b882a 100644
--- a/board/webidl.md
+++ b/board/webidl.md
@@ -4,70 +4,77 @@ Web IDL for Board and IO APIs
interface Board {
readonly attribute String name; // board name, e.g. "arduino101"
- attribute EventHandler onerror;
+ readonly attribute String os; // OS name, e.g. "Zephyr-1.0"
- Promise aio(PinName pin);
- Promise gpio(PinName or GPIOOptions options);
- Promise pwm( (PinName or PWMOptions) options);
- Promise i2c(I2COptions options);
- Promise spi(SPIOptions options);
- Promise uart(UARTOptions options);
+ readonly attribute EventHandler onerror;
};
Board implements EventEmitter;
typedef (long or unsigned long or double or unrestricted double) Number;
typedef (DOMString or USVString) String;
-typedef (Number or String) PinName; // implementation uses board specific mapping
+typedef (Number or String) PinName;
-interface Pin {
- readonly attribute PinName pin; // board number/name of the pin
-};
+enum PinMapping { "board", "system" };
// AIO
+interface AIOObject {
+ AIO open((PinName or AIOOptions) init);
+};
dictionary AIOOptions {
PinName pin;
- unsigned long precision;
+ PinMapping mapping = "board";
+ unsigned long precision = 10;
};
[NoInterfaceObject]
-interface AIO: Pin {
+interface AIO {
+ readonly attribute PinName pin;
readonly attribute unsigned long precision; // 10 or 12 bits
unsigned long read();
void close();
};
-AIO implements EventEmitter;
-
// GPIO
-enum GPIOMode { "input", "output" };
-enum GPIOEdge { "none", "rising", "falling", "any" };
-enum GPIOState { "pull-up", "pull-down", "high-impedance" };
-
-dictionary GPIOOptions {
- PinName pin;
- sequence port; // GPIO Ports (8, 16 or 32 pins)
- GPIOMode mode = "input";
- boolean activeLow = false;
- GPIOEdge edge = "any";
- GPIOState state = "high-impedance";
+interface GPIOObject {
+ GPIO open((PinName or GPIOOptions) init);
+ GPIO port((PinName or sequence) port, optional GPIOOptions init);
};
[NoInterfaceObject]
-interface GPIO: Pin {
- unsigned long read();
- void write(long value);
- void close();
- attribute EventHandler ondata;
+interface GPIO: {
+ unsigned long read();
+ void write(long value);
+ void close();
+
+ attribute EventHandler ondata;
};
GPIO implements EventEmitter;
+dictionary GPIOOptions {
+ PinName pin;
+ PinMapping mapping = "board";
+ GPIOMode mode = "out";
+ boolean activeLow = false;
+ GPIOEdge edge = "none";
+ GPIOState state = "high-impedance";
+};
+
+enum GPIOMode { "in", "out" };
+enum GPIOEdge { "none", "rising", "falling", "any" };
+enum GPIOState { "pull-up", "pull-down", "high-impedance" };
+
// PWM
+interface PWMObject {
+ PWM open((PinName or PWMOptions) init);
+};
+
dictionary PWMOptions {
PinName pin;
+ PinMapping mapping = "board";
boolean reversePolarity = false;
double period;
double pulseWidth;
@@ -75,14 +82,26 @@ dictionary PWMOptions {
};
[NoInterfaceObject]
-interface PWM: Pin {
- readonly attribute boolean reversePolarity;
- void write(PWMOptions value);
- void stop();
- void close();
+interface PWM {
+ readonly attribute PinName pin;
+ readonly attribute boolean reversePolarity;
+
+ void write(PWMValue value);
+ void stop();
+ void close();
+};
+
+dictionary PWMValue {
+ double period;
+ double pulseWidth;
+ double dutyCycle;
};
// I2C
+interface I2CObject {
+ I2C open(I2COptions options);
+};
+
dictionary I2COptions {
octet bus;
unsigned long speed; // 10, 100, 400, 1000, 3400 kbps
@@ -93,12 +112,15 @@ interface I2C {
readonly attribute octet bus;
readonly attribute unsigned long speed;
- Promise read(octet device, unsigned long size);
- Promise write(octet device, Buffer data);
+ Buffer read(octet device, unsigned long size);
+ void write(octet device, Buffer data);
void close();
};
// SPI
+interface SPIObject {
+ SPI open(SPIOptions options);
+};
enum SPITopology { "full-duplex", "single-write", "single-read", "daisy-chain" };
@@ -116,11 +138,15 @@ dictionary SPIOptions {
[NoInterfaceObject]
interface SPI {
// has all the properties of SPIOptions as read-only attributes
- Promise transfer(octet device, Buffer txData);
+ Buffer transfer(octet device, Buffer txData);
void close();
};
// UART
+interface UARTObject {
+ UART open(UARTOptions options);
+};
+
enum UARTParity { "none", "even", "odd" };
dictionary UARTOptions {
@@ -135,7 +161,7 @@ dictionary UARTOptions {
[NoInterfaceObject]
interface UART {
// has all the properties of UARTInit as read-only attributes
- Promise write(Buffer data);
+ void write(Buffer data);
void setReadRange(long minBytes, long maxBytes);
attribute EventHandler ondata;
void close();