Skip to main content

Digital IO (GPIO)

DeviceScript provides access to digital GPIO (General Purpose Input/Output) operations on pins that do not require precise real time timings.

It is recommend to encapsulate the GPIO access into server implementation as they are rather low level.

caution

If your application needs consistent response times of under 10ms, you can either implement the driver natively in C using interrupts, or better yet offload it to an external Jacdac module.

Pin mappings

While you can use hardware GPIO numbers with the ds.gpio() function, it is highly recommended that you instead import a board definition file an use pin names matching silk on the hardware.

import { pins } from "@dsboard/adafruit_qt_py_c3"

const A2 = pins.A2_D2

The doc-string for pins.A2_D2 will tell you GPIO number (1 in this case). Using named pins is also less error-prone since pins used for internal functions are not exposed through the pins object and the pins that are exposed are annotated with type (input, output, analog, etc.) which is then required by the startSomething() functions.

Pins generally share names for boards with the same pinout. In particular, QT Py and XIAO share names.

The gpio() function does not check for pin functions or usage. It will return undefined when named pin is not available or used for something else.

import { gpio } from "@devicescript/core"

const P0 = gpio(0)

Mode

The pin can be access through the generic gpio function or through board specific packages that provide predefined pin mappings (see devices).

You can configure the input/output mode through setMode.

import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"

// p0 -> output
const p0 = gpio(0)
await p0.setMode(GPIOMode.Output)

// P1 -> input
const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)

Output

Use write to set the output value of a pin. This example flips a pin state every second.

import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"

const p0 = gpio(0)
await p0.setMode(GPIOMode.Output)

let loop = 0
setInterval(async () => {
await p0.write(loop++ % 2)
}, 1000)

Input

Use value to read the input value of a pin. This example reads the input value every second.

import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"

const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)

// polling read pin
setInterval(async () => {
const v = p1.value
console.log({ poll: v })
}, 1000)

Use subscribe to run code whenever the pin changes state.

import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"

const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)

p1.subscribe(v => console.log({ sub: v }))