Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions ble/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,8 @@ The `startadvertising()` method runs the following steps:
<a name="stopadvertising"></a>
##### 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"`.

<a name="addservice"></a>
##### The `addService(service)` method
Expand Down Expand Up @@ -288,17 +286,13 @@ The `needsResponse` property is a boolean that is by default `true`.
<a name="respond"></a>
##### 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"`.

<a name="errormethod"></a>
##### 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"`.
6 changes: 3 additions & 3 deletions ble/webidl.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface BluetoothPeripheralDevice {

Promise<AdvertisingOptions> startAdvertising(Advertisement advertisement,
optional AdvertisingOptions options);
Promise stopAdvertising();
void stopAdvertising(); // Promise?

readonly attribute boolean enabled;
attribute EventHandler onenabledchange;
Expand Down Expand Up @@ -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"};
Expand Down
122 changes: 24 additions & 98 deletions board/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

<a name="pin"></a>
### 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`.

<a name="board"></a>
### 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 |

<a name="name"></a>
<a name="boardname"></a>
The `name` property is read-only, and provides the board name.

<a name="version"></a>
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).
<a name="osname"></a>
The `os` property is read-only, and provides the underlying operating system name.

<a name="apiversion"></a>
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).

<a name="error"></a>
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

<a name="aio"></a>
##### 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.

<a name="gpio"></a>
##### 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.

<a name="pwm"></a>
##### 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.

<a name="i2c"></a>
##### 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.

<a name="spi"></a>
##### 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.

<a name="uart"></a>
##### 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.
85 changes: 46 additions & 39 deletions board/aio.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
<a name="apiobject"></a>
### The AIO API object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should name this ADC since there's no output? We've called it AIO for a long time in ZJS but maybe it should change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some boards DAC is supported, but it's rare. I will check again.

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.

<a name="open"></a>
#### 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.

<a name="aio"></a>
### 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 |
Expand All @@ -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.

<a name="init"></a>
#### 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.

<a name="read"></a>
#### The `unsigned long read()` method
Performs a synchronous read operation for the pin value. It returns the pin value representing the last sampling.

<a name="close"></a>
#### 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);
};
```
Loading