DOCUMENTATION BASE Reference
Overview
Getting Started
BASE
Reference
Worker
Setup modules
COMMODETTO
Reference
Poco Renderer
Outlines
Creating Fonts
Crypt
Data
DEVICES
Moddable One
Moddable Two
Moddable Three
Moddable Four
Moddable Six
ESP32
ESP8266
nRF52
nRF52 Low Power Notes
Raspberry Pi Pico
M5Core Ink
M5Paper
Wasm
SiLabs Gecko
QCA4020
Moddable Zero
Moddable Display Developer Guide
DISPLAYS
Overview
Adafruit 1.8" ST7735
Adafruit OLED Display
BuyDisplay 2.8" CTP - ESP8266
Crystalfontz ePaper
DotStar
Generic 1.44"
Generic 2.4" & 2.8" (Resistive Touch) - ESP32
Generic 2.4" & 2.8" (Resistive Touch) - ESP8266
Generic 2.4" & 2.8" (Resistive Touch) - Pico
Sharp Memory
Sharp Memory Screen 1.3"
SparkFun TeensyView
Switch Science Reflective LCD
DRIVERS
DESTM32S display
DotStar display
ILI9341 display
LPM013M126A display
LS013B4DN04 display
MCP230XX GPIO expander
NeoStrand
SSD1306 display
SSD1351 display
ST7735 display
Files
IO
TC53 IO
Firmata
NETWORK
Reference
TLS (SecureSocket)
BLE
Ethernet
Web Things
PINS
Reference
Audio Output
PIU
Reference
Localization
Keyboard
Expanding Keyboard
Die Cut
Using After Effects Motion Data
TOOLS
Reference
Manifest
Defines in Manifests
Testing
XS
Handle
JavaScript language considerations on embedded devices using the XS engine
Mods – User Installed Extensions
ROM Colors
Using XS Preload to Optimize Applications
XS Conformance
XS Marshalling
XS Platforms
XS in C
XS linker warnings
xsbug
xst
XS Compartment
XS Profiler
XS Scopes

Base

Copyright 2017-2024 Moddable Tech, Inc.
Revised: January 19, 2024

Table of Contents

class Timer

The Timer class provides both time-based callbacks and a delay function.

import Timer from "timer";

Timer callbacks are invoked with this set to globalThis. Use an arrow function or Function.prototype.bind to bind the callback's this to another value.

Each timer has two intervals: the initial interval and a repeat interval. The intervals are in milliseconds. The initial interval is the time until the callback is first invoked. The repeat interval is the time between successive invocations of the callback after the initial interval. The API reference that follows indicates how each API modifies the initial and repeat intervals.

If the repeat interval is zero when the timer's callback returns, the timer is automatically cleared and can no longer be used. The repeat interval may be changed by the callback using Timer.schedule.

The Timer.set and Timer.repeat functions create a new timer and return the ID of the timer. Timer IDs are opaque that are only useful for passing to Timer functions.

Timer callbacks can provide the basic behaviors of setImmediate, setTimeout and setInterval. The timers example shows how to do this.

Timer.set(callback[, initialInterval, repeatInterval])

The set function requests a function be called once after a certain period. Timer.set returns the new timer's ID.

An immediate timer is called on the next cycle through the run loop. To set an immediate timer, call set with a single argument.

Timer.set(id => trace("immediate fired\n"));

A one shot timer is called once after a specified number of milliseconds. If the number of milliseconds is zero, a one shot timer is equivalent to an immediate timer.

Timer.set(id => trace("one shot fired\n"), 1000);

Calling set with a repeat is equivalent to a repeating timer with the first callback triggered after the interval.

Timer.set(id => trace("repeat fired\n"), 1000, 100);

The callback function receives the timer id as the first argument.

If Timer.set is called without the initial interval and repeat interval, it is an immediate one-shot timer (initial and repeat intervals are set to 0). If Timer.set is called with only an initial interval, it is a one-shot timer (repeat interval is set to 0). If Timer.set is called with both an initial and a non-zero repeat interval, it is a repeating timer.


Timer.repeat(callback, repeatInterval)

A repeating timer is called continuously until stopped using the Timer.clear function. Timer.repeat returns the new timer's ID.

Timer.repeat(id => trace("repeat fired\n"), 1000);

The callback function receives the timer id as the first argument.

This function sets both the initial interval and repeat interval to the value specified by repeatInterval. Use Timer.set to create a timer with an initial interval that is different from the repeat interval.


Timer.schedule(id [, initialInterval[, repeatInterval]])

The schedule function reschedules or unschedules an existing timer.

If called with an initial interval but no repeat interval, the timer behaves like a one shot timer created with Timer.set. If called with both an initial interval and non-zero repeat interval, it behaves like a repeating timer created with Timer.set with both initial interval and repeat interval arguments. If called without interval arguments, the timer is unscheduled and will not trigger until rescheduled using Timer.schedule (an unscheduled timer is considered to have infinite initial and repeat intervals).

In the following example, the callback function is triggered twice at one second intervals and then rescheduled to once every two seconds.

let state = 0;
Timer.repeat(id => {
	if (0 == state)
		state = 1;
	else if (1 == state) {
		state = 2;
		Timer.schedule(id, 2000, 2000);
	}
}, 1000);

When Timer.schedule is used to set the initial interval, the callback is next invoked after the new initial interval has elapsed.

Note: If the next trigger time is unknown, unscheduling a timer is preferred to scheduling for a long time in the future. Unscheduling and rescheduling a timer can more efficient than clearing a timer and later allocating a new one.


Timer.clear(id)

The clear function cancels a timer. The Timer.set and Timer.repeat functions returns the ID for a timer, which is then passed to clear.

let aTimer = Timer.set(id => trace("one shot\n"), 1000);
Timer.clear(aTimer);

Note: Immediate and one shot timers are automatically cleared after invoking their callback function. There is no need to call clear except to cancel the timer before it fires.

Note: If Timer.clear is passed a value of undefined or null for the ID, no exception is generated.


Timer.delay(ms)

The delay function delays execution for the specified number of milliseconds.

Timer.delay(500);	// delay 1/2 second

Note: In general, the preferred style of JavaScript programming is to avoid long delays that block execution. Timer.delay is provided because in embedded development it is common to need short delays when interacting with hardware. For longer delays, using an alternative such as a Timer callback or asynchronous execution with Promises may be more appropriate.


class Time

The Time class provides time functions and a tick counter.

import Time from "time";

Time.set(seconds)

The set function sets the system time. The seconds argument corresponds to the number of seconds elapsed since January 1, 1970, i.e. Unix time.


timezone property

The timezone property is set to the time zone offset in seconds from UTC.

Time.timezone = +9 * 60 * 60;	// Set time zone to UTC+09:00

dst property

The dst property is set to the daylight saving time (DST) offset in seconds.

Time.dst = 60 * 60;	// Set DST

ticks property

The ticks property returns the value of a millisecond counter. The value returned does not correspond to the time of day. The milliseconds are used to calculate time differences.

const start = Time.ticks;
for (let i = 0; i < 1000; i++)
	;
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.

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.


Time.delta(start[, end])

The delta function calculates the difference between two values returned by Time.ticks. It is guaranteed to return a correct result even when the value rolls over. If the optional end argument is omitted the current value of Time.ticks is used.


microseconds property (optional)

The microseconds property returns the value of a microseconds counter. The value returned does not correspond to the time of day. The microseconds are used to calculate time differences.

To use the microseconds property, include its manifest in the project manifest:

	"include": [
		...
		"$(MODDABLE)/modules/base/microseconds/manifest.json",
	],

The microseconds property is used in the same way as the ticks property. Like the ticks property, a single time source is used when there multiple concurrent virtual machines. The range of the microseconds property is a 64-bit floating point value.

Unlike Time.ticks, the values returned by Time.microseconds may always be subtracted from one another to calculate intervals.

const start = Time.microseconds;
for (let i = 0; i < 1000; i++)
	;
const stop = Time.microseconds;
trace(`Operation took ${stop - start} microseconds\n`);

Note: Not all hosts implement microseconds. Hosts that do not implement microseconds generate an error at build time.


class Debug

The Debug class provides functions that are useful during the development process.

import Debug from "debug";

Debug.gc([enable])

The gc function can be used to turn the JavaScript garbage collector on and off, as well as to run the garbage collector on-demand.

Calling Debug.gc with no arguments runs the garbage collector immediately.

Debug.gc();

Calling Debug.gc with a single boolean argument enables or disables the garbage collector.

Debug.gc(true)	// enable garbage collector
Debug.gc(false);	// disable garbage collector

class UUID

The UUID class provides a single function to generate a UUID string.

import UUID from "uuid";

Note: Generating a truly unique UUID requires that the device running this function have a unique MAC address and the valid time. Neither of these is guaranteed on all microcontrollers. For production software release, check your device configuration.

UUID()

The UUID function returns a new UUID formatted as a string.

let value = UUID();	// 1080B49C-59FC-4A32-A38B-DE7E80117842

function deepEqual(a, b [,options])

The deepEqual function implements a deep comparison between two JavaScript object.

import deepEqual from "deepEqual";

There is no standard algorithm for deeply comparing two objects in JavaScript, and there are many possible correct approaches. The Moddable SDK adopts the behavior of assert.deepEqual and assert.deepStrictEqual from Node.js for its implementation of deepEqual.

The deepEqual function has an optional third parameter, an options object. By default the deepEqual comparison is not-strict, similar to using == for comparisons. Passing {strict: true} for the options object uses strict comparison, similar to using === for comparisons.

const a = {a: 1, b: 0, c: "str"};
const b = {a: 1, b: "0", c: "str"};
deepEqual(a, b);		// true
deepEqual(a, b, {strict: true});		// false

The known differences between the Moddable SDK implementation and Node.js will not impact most uses:

  • WeakMap and WeakSet using read-only objects as keys
  • XS does not call valueOf to compare boxed primitives

function structuredClone(object[, transferables])

The structuredClone function creates a deep copy of a JavaScript object.

import structuredClone from "structuredClone";

The structuredClone function in the Moddable SDK implements the algorithm defined by WHATWG for the web platform as much as practical, including circular references and the transferables option.

const a = {a: 1, b: Uint8Array.of(1, 2, 3)}
const aCopy = structuredClone(a);

The Moddable SDK implementation of structuredClone implements all supported types that are part of the JavaScript language standard. It does not, of course, clone object types that are part of the web platform and not present on embedded systems such as DOMException.

class Instrumentation

The Instrumentation class returns statistics on the behavior of the runtime, including memory use, open file count, and rendering frame rate.

import Instrumentation from "instrumentation";

get(what)

The get function returns the value of the instrumented item at the index specified by the what parameter. Instrumented items are consecutively numbered starting at index 1.

let pixelsDrawn = Instrumentation.get(1);

The index of instrumentation items depends on the host and varies between different devices based on the supported features. Use Instrumentation.map() to determine the index of a specific instrumentation on the running host.

map(name)

The map function returns the instrumentation index for a name.

let pixelsDrawnIndex = Instrumentation.map("Pixels Drawn");
let pixelsDrawn = Instrumentation.get(pixelsDrawnIndex);

If the instrumentation item named is unavailable, map returns undefined.

name(index)

The name function returns the name of the instrumentation item at the specified index. It can be used to iterate through all available instrumentation items.

for (let i = 1; true; i++) {
	const name = Instrumentation.name(i);
	if (!name)
		break;
	trace(`${name}: ${Instrumentation.get(i)}\n`);
}

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.

Name Long Description
Pixels Drawn The total number of pixels rendered to by Poco during the current interval. This value includes pixels drawn to a display device and pixels rendered offscreen.
Frames Drawn The total number of frames rendered by Poco during the most recent interval. Frames are counted by calls to Poco.prototype.end() and by Piu frame updates.
Network Bytes Read The total number of bytes received by the Socket module during the current interval. This includes bytes received over TCP and UDP.
Network Bytes Written The total number of bytes send by the Socket module during the current interval. This includes bytes sent using TCP and UDP.
Network Sockets The total number of active network sockets created by the Socket module. This includes TCP sockets, TCP listeners, and UDP sockets.
Timers The number of allocated timers created by the Timer module.
Files The number of open files and directory iterators created the File module.
Poco Display List Used The peak size in bytes of the Poco display list in the current interval.
Piu Command List Used The peak size in bytes of the Piu command list in the current interval.
Turns The number of times the event loop has run in the current interval.
CPU 0 The load on CPU 0 during the current interval.
CPU 1 The load on CPU 1 during the current interval.
System Free Memory The number of free bytes in the system memory heap. This value is not available in the simulator.
XS Slot Heap Used Number of bytes in use in the slot heap of the primary XS machine. Some of these bytes may be freed when the garbage collector next runs.
XS Chunk Heap Used Number of bytes in use in the chunk heap of the primary XS machine. Some of these bytes may be freed when the garbage collector next runs.
XS Keys Used Number of runtime keys allocated by the primary XS machine. Once allocated keys are never deallocated.
XS Garbage Collection Count The number of times the garbage collector has run in the current interval.
XS Modules Loaded The number of JavaScript modules that are currently loaded in the primary XS machine. This number does not include modules which are preloaded.
XS Stack Used The maximum depth in bytes of the stack of the primary XS virtual machine during the current interval.
XS Promises Settled The number of Promises settled. This is useful as a measure of Promisee/async/await activity.

class Console

The Console class implements a serial terminal for debugging and diagnostic purposes. The Console module uses CLI modules to implement the terminal commands.


class CLI

The CLI class is a plug-in interface for commands used in a command line interface. CLI classes implement commands for use by the Console module (serial command line) and Telnet module (network command line).


class Worker

See the Worker documentation for information about the Worker class.