Merge pull request #3383 from bobrippling/apps/ctrlpad

New app: ctrlpad
pull/3351/head
thyttan 2024-04-29 09:59:31 +02:00 committed by GitHub
commit 93039b7de5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1193 additions and 175 deletions

View File

@ -4,3 +4,15 @@ apps/gipy/pkg/gps.js
# Needs to be ignored because it includes broken JS
apps/health/chart.min.js
# TypeScript
apps/btadv/
apps/clkinfostopw/
apps/ctrlpad/
apps/drained/
apps/folderlaunch/
apps/popconlaunch/
apps/rep/
apps/widChargingStatus/
apps/widbtstates/
apps/widhid/

1
apps/ctrlpad/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: New app - forked from widhid

24
apps/ctrlpad/README.md Normal file
View File

@ -0,0 +1,24 @@
# Description
A control pad app to provide fast access to common functions, such as bluetooth power, HRM and Do Not Disturb.
By dragging from the top of the watch, you have this control without leaving your current app (e.g. on a run, bike ride or just watching the clock).
The app is designed to not conflict with other gestures - when the control pad is visible, it'll prevent propagation of events past it (touch, drag and swipe specifically). When the control pad is hidden, it'll ignore touch, drag and swipe events with the exception of an event dragging from the top 40 pixels of the screen.
# Usage
Swipe down to enable and observe the overlay being dragged in. Swipe up on the overlay to hide it again. Then tap on a given button to trigger it.
Requires espruino firmware > 2v17 to avoid event handler clashes.
# Setup / Technical details
The control pad disables drag and touch event handlers while active, preventing other apps from interfering.
# Todo
- Handle rotated screen (`g.setRotation(...)`)
- Handle notifications (sharing of `setLCDOverlay`)

1
apps/ctrlpad/icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("lcshAzwp9WlgAXldWp8rp5bIq1drwAdq0rFI1XBodXAC4rErorEFIlWLAOCAC2IxGCFY9WA4VWCAQAbJgavBlanCqwodFYpWBp4pCKbwACQYVQfoJUUruBD4dXBQeBBQZWCQIIqBq9dFSNXD4eBFQldDwgqBq4qDP4xEBqwKHFS6qFwVWQ4OsAgYqhAoOtAAYsBFUAbBFImI1uBDIgqQq4qJqwpEwIGCKwgqEroKEFQhsBFRNPwIACVIIECp4qHq16CAKATCAIACqwFEFQxIB6/XRoZVQABwqHLgQqiQAWAQBAqeD4IEDVaLRBABAqJq4qJq5VdwIqKQDwqWQBtXqoUDFQmBCAI2DKq+BvXX6wxCFQb6B6/XEAYqXrurD4N6CoIqDwOBBQIDBQCY1FJQOs1hVIBQgqLwQAFKwwgBVZAKFQDAlCCYYqEBQoqaq4qJrtdFTzJCFX4qoS4gqmCwYqewQqFQIIqhq9XEoNPp4qCQKOBCQeCPQgKEKAdWlYEBrpWSABtWKgNelcAQIdXFbxQBEYQqBgErrpXDq+CADBIBKYRUCAAKCBFYQsCADAoDrzTBFQRWBlZfCADp9BFIgACp4tCq4AYqxMCFAwAEBhgAWA=="))

BIN
apps/ctrlpad/icon.js.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
apps/ctrlpad/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

314
apps/ctrlpad/main.js Normal file
View File

@ -0,0 +1,314 @@
(function () {
if (!Bangle.prependListener) {
Bangle.prependListener = function (evt, listener) {
var handlers = Bangle["#on".concat(evt)];
if (!handlers) {
Bangle.on(evt, listener);
}
else {
if (typeof handlers === "function") {
Bangle.on(evt, listener);
}
Bangle["#on".concat(evt)] = [listener].concat(handlers.filter(function (f) { return f !== listener; }));
}
};
}
var Overlay = (function () {
function Overlay() {
this.width = g.getWidth() - 10 * 2;
this.height = g.getHeight() - 24 - 10;
this.g2 = Graphics.createArrayBuffer(this.width, this.height, 4, { msb: true });
this.renderG2();
}
Overlay.prototype.setBottom = function (bottom) {
var g2 = this.g2;
var y = bottom - this.height;
Bangle.setLCDOverlay(g2, 10, y - 10);
};
Overlay.prototype.hide = function () {
Bangle.setLCDOverlay();
};
Overlay.prototype.renderG2 = function () {
this.g2
.reset()
.setColor(g.theme.bg)
.fillRect(0, 0, this.width, this.height)
.setColor(colour.on.bg)
.drawRect(0, 0, this.width - 1, this.height - 1)
.drawRect(1, 1, this.width - 2, this.height - 2);
};
return Overlay;
}());
var colour = {
on: {
fg: "#fff",
bg: "#00a",
},
off: {
fg: "#000",
bg: "#bbb",
},
};
var Controls = (function () {
function Controls(g, controls) {
var height = g.getHeight();
var centreY = height / 2;
var circleGapY = 30;
var width = g.getWidth();
this.controls = [
{ x: width / 4 - 10, y: centreY - circleGapY },
{ x: width / 2, y: centreY - circleGapY },
{ x: width * 3 / 4 + 10, y: centreY - circleGapY },
{ x: width / 3, y: centreY + circleGapY },
{ x: width * 2 / 3, y: centreY + circleGapY },
].map(function (xy, i) {
var ctrl = xy;
var from = controls[i];
ctrl.text = from.text;
ctrl.cb = from.cb;
Object.assign(ctrl, from.cb(false) ? colour.on : colour.off);
return ctrl;
});
}
Controls.prototype.draw = function (g, single) {
g
.setFontAlign(0, 0)
.setFont("4x6:3");
for (var _i = 0, _a = single ? [single] : this.controls; _i < _a.length; _i++) {
var ctrl = _a[_i];
g
.setColor(ctrl.bg)
.fillCircle(ctrl.x, ctrl.y, 23)
.setColor(ctrl.fg)
.drawString(ctrl.text, ctrl.x, ctrl.y);
}
};
Controls.prototype.hitTest = function (x, y) {
var dist = Infinity;
var closest;
for (var _i = 0, _a = this.controls; _i < _a.length; _i++) {
var ctrl = _a[_i];
var dx = x - ctrl.x;
var dy = y - ctrl.y;
var d = Math.sqrt(dx * dx + dy * dy);
if (d < dist) {
dist = d;
closest = ctrl;
}
}
return dist < 30 ? closest : undefined;
};
return Controls;
}());
var state = 0;
var startY = 0;
var startedUpDrag = false;
var upDragAnim;
var ui;
var touchDown = false;
var initUI = function () {
if (ui)
return;
var controls = [
{
text: "BLE",
cb: function (tap) {
var on = NRF.getSecurityStatus().advertising;
if (tap) {
if (on)
NRF.sleep();
else
NRF.wake();
}
return on !== tap;
}
},
{
text: "DnD",
cb: function (tap) {
var on;
if (on = !!origBuzz) {
if (tap) {
Bangle.buzz = origBuzz;
origBuzz = undefined;
}
}
else {
if (tap) {
origBuzz = Bangle.buzz;
Bangle.buzz = function () { return Promise.resolve(); };
setTimeout(function () {
if (!origBuzz)
return;
Bangle.buzz = origBuzz;
origBuzz = undefined;
}, 1000 * 60 * 10);
}
}
return on !== tap;
}
},
{
text: "HRM",
cb: function (tap) {
var _a;
var id = "widhid";
var hrm = (_a = Bangle._PWR) === null || _a === void 0 ? void 0 : _a.HRM;
var off = !hrm || hrm.indexOf(id) === -1;
if (off) {
if (tap)
Bangle.setHRMPower(1, id);
}
else if (tap) {
Bangle.setHRMPower(0, id);
}
return !off !== tap;
}
},
{
text: "clk",
cb: function (tap) {
if (tap)
Bangle.showClock(), terminateUI();
return true;
},
},
{
text: "lch",
cb: function (tap) {
if (tap)
Bangle.showLauncher(), terminateUI();
return true;
},
},
];
var overlay = new Overlay();
ui = {
overlay: overlay,
ctrls: new Controls(overlay.g2, controls),
};
ui.ctrls.draw(ui.overlay.g2);
};
var terminateUI = function () {
state = 0;
ui === null || ui === void 0 ? void 0 : ui.overlay.hide();
ui = undefined;
};
var onSwipe = function () {
var _a;
switch (state) {
case 0:
case 2:
return;
case 1:
case 3:
(_a = E.stopEventPropagation) === null || _a === void 0 ? void 0 : _a.call(E);
}
};
Bangle.prependListener('swipe', onSwipe);
var onDrag = (function (e) {
var _a, _b, _c;
var dragDistance = 30;
if (e.b === 0)
touchDown = startedUpDrag = false;
switch (state) {
case 2:
if (e.b === 0)
state = 0;
break;
case 0:
if (e.b && !touchDown) {
if (e.y <= 40) {
state = 1;
startY = e.y;
(_a = E.stopEventPropagation) === null || _a === void 0 ? void 0 : _a.call(E);
}
else {
state = 2;
}
}
break;
case 1:
if (e.b === 0) {
if (e.y > startY + dragDistance) {
initUI();
state = 3;
startY = 0;
Bangle.prependListener("touch", onTouch);
Bangle.buzz(20);
ui.overlay.setBottom(g.getHeight());
}
else {
terminateUI();
break;
}
}
else {
var dragOffset = 32;
initUI();
ui.overlay.setBottom(e.y - dragOffset);
}
(_b = E.stopEventPropagation) === null || _b === void 0 ? void 0 : _b.call(E);
break;
case 3:
(_c = E.stopEventPropagation) === null || _c === void 0 ? void 0 : _c.call(E);
if (e.b) {
if (!touchDown) {
startY = e.y;
}
else if (startY) {
var dist = Math.max(0, startY - e.y);
if (startedUpDrag || (startedUpDrag = dist > 10))
ui.overlay.setBottom(g.getHeight() - dist);
}
}
else if (e.b === 0) {
if ((startY - e.y) > dragDistance) {
var bottom_1 = g.getHeight() - Math.max(0, startY - e.y);
if (upDragAnim)
clearInterval(upDragAnim);
upDragAnim = setInterval(function () {
if (!ui || bottom_1 <= 0) {
clearInterval(upDragAnim);
upDragAnim = undefined;
terminateUI();
return;
}
ui.overlay.setBottom(bottom_1);
bottom_1 -= 30;
}, 50);
Bangle.removeListener("touch", onTouch);
state = 0;
}
else {
ui.overlay.setBottom(g.getHeight());
}
}
break;
}
if (e.b)
touchDown = true;
});
var onTouch = (function (_btn, xy) {
var _a;
if (!ui || !xy)
return;
var top = g.getHeight() - ui.overlay.height;
var left = (g.getWidth() - ui.overlay.width) / 2;
var ctrl = ui.ctrls.hitTest(xy.x - left, xy.y - top);
if (ctrl) {
onCtrlTap(ctrl, ui);
(_a = E.stopEventPropagation) === null || _a === void 0 ? void 0 : _a.call(E);
}
});
var origBuzz;
var onCtrlTap = function (ctrl, ui) {
Bangle.buzz(20);
var col = ctrl.cb(true) ? colour.on : colour.off;
ctrl.fg = col.fg;
ctrl.bg = col.bg;
ui.ctrls.draw(ui.overlay.g2, ctrl);
};
Bangle.prependListener("drag", onDrag);
Bangle.on("lock", terminateUI);
})();

418
apps/ctrlpad/main.ts Normal file
View File

@ -0,0 +1,418 @@
(() => {
if(!Bangle.prependListener){
type Event<T> = T extends `#on${infer Evt}` ? Evt : never;
Bangle.prependListener = function(
evt: Event<keyof BangleEvents>,
listener: () => void
){
// move our drag to the start of the event listener array
const handlers = (Bangle as BangleEvents)[`#on${evt}`]
if(!handlers){
Bangle.on(evt as any, listener);
}else{
if(typeof handlers === "function"){
// get Bangle to convert to array
Bangle.on(evt as any, listener);
}
// shuffle array
(Bangle as BangleEvents)[`#on${evt}`] = [listener as any].concat(
(handlers as Array<any>).filter((f: unknown) => f !== listener)
);
}
};
}
class Overlay {
g2: Graphics;
width: number;
height: number;
constructor() {
// x padding: 10 each side
// y top: 24, y bottom: 10
this.width = g.getWidth() - 10 * 2;
this.height = g.getHeight() - 24 - 10;
this.g2 = Graphics.createArrayBuffer(
this.width,
this.height,
/*bpp*/4,
{ msb: true }
);
this.renderG2();
}
setBottom(bottom: number): void {
const { g2 } = this;
const y = bottom - this.height;
Bangle.setLCDOverlay(g2, 10, y - 10);
}
hide(): void {
Bangle.setLCDOverlay();
}
renderG2(): void {
this.g2
.reset()
.setColor(g.theme.bg)
.fillRect(0, 0, this.width, this.height)
.setColor(colour.on.bg)
.drawRect(0, 0, this.width - 1, this.height - 1)
.drawRect(1, 1, this.width - 2, this.height - 2);
}
}
type ControlCallback = (tap: boolean) => boolean | number;
type Control = {
x: number,
y: number,
fg: ColorResolvable,
bg: ColorResolvable,
text: string,
cb: ControlCallback,
};
const colour = {
on: {
fg: "#fff",
bg: "#00a",
},
off: {
fg: "#000",
bg: "#bbb",
},
} as const;
type FiveOf<X> = [X, X, X, X, X];
type ControlTemplate = { text: string, cb: ControlCallback };
class Controls {
controls: FiveOf<Control>;
constructor(g: Graphics, controls: FiveOf<ControlTemplate>) {
// const connected = NRF.getSecurityStatus().connected;
// if (0&&connected) {
// // TODO
// return [
// { text: "<", cb: hid.next },
// { text: "@", cb: hid.toggle },
// { text: ">", cb: hid.prev },
// { text: "-", cb: hid.down },
// { text: "+", cb: hid.up },
// ];
// }
const height = g.getHeight();
const centreY = height / 2;
const circleGapY = 30;
const width = g.getWidth();
this.controls = [
{ x: width / 4 - 10, y: centreY - circleGapY },
{ x: width / 2, y: centreY - circleGapY },
{ x: width * 3/4 + 10, y: centreY - circleGapY },
{ x: width / 3, y: centreY + circleGapY },
{ x: width * 2/3, y: centreY + circleGapY },
].map((xy, i) => {
const ctrl = xy as Control;
const from = controls[i]!;
ctrl.text = from.text;
ctrl.cb = from.cb;
Object.assign(ctrl, from.cb(false) ? colour.on : colour.off);
return ctrl;
}) as FiveOf<Control>;
}
draw(g: Graphics, single?: Control): void {
g
.setFontAlign(0, 0)
.setFont("4x6:3" as any);
for(const ctrl of single ? [single] : this.controls){
g
.setColor(ctrl.bg)
.fillCircle(ctrl.x, ctrl.y, 23)
.setColor(ctrl.fg)
.drawString(ctrl.text, ctrl.x, ctrl.y);
}
}
hitTest(x: number, y: number): Control | undefined {
let dist = Infinity;
let closest;
for(const ctrl of this.controls){
const dx = x-ctrl.x;
const dy = y-ctrl.y;
const d = Math.sqrt(dx*dx + dy*dy);
if(d < dist){
dist = d;
closest = ctrl;
}
}
return dist < 30 ? closest : undefined;
}
}
const enum State {
Idle,
TopDrag,
IgnoreCurrent,
Active,
}
type UI = { overlay: Overlay, ctrls: Controls };
let state = State.Idle;
let startY = 0;
let startedUpDrag = false;
let upDragAnim: IntervalId | undefined;
let ui: undefined | UI;
let touchDown = false;
const initUI = () => {
if (ui) return;
const controls: FiveOf<ControlTemplate> = [
{
text: "BLE",
cb: tap => {
const on = NRF.getSecurityStatus().advertising;
if(tap){
if(on) NRF.sleep();
else NRF.wake();
}
return on !== tap; // on ^ tap
}
},
{
text: "DnD",
cb: tap => {
let on;
if(on = !!origBuzz){
if(tap){
Bangle.buzz = origBuzz;
origBuzz = undefined;
}
}else{
if(tap){
origBuzz = Bangle.buzz;
Bangle.buzz = () => Promise.resolve();
setTimeout(() => {
if(!origBuzz) return;
Bangle.buzz = origBuzz;
origBuzz = undefined;
}, 1000 * 60 * 10);
}
}
return on !== tap; // on ^ tap
}
},
{
text: "HRM",
cb: tap => {
const id = "widhid";
const hrm = (Bangle as any)._PWR?.HRM as undefined | Array<string> ;
const off = !hrm || hrm.indexOf(id) === -1;
if(off){
if(tap)
Bangle.setHRMPower(1, id);
}else if(tap){
Bangle.setHRMPower(0, id);
}
return !off !== tap; // on ^ tap
}
},
{
text: "clk",
cb: tap => {
if (tap) Bangle.showClock(), terminateUI();
return true;
},
},
{
text: "lch",
cb: tap => {
if (tap) Bangle.showLauncher(), terminateUI();
return true;
},
},
];
const overlay = new Overlay();
ui = {
overlay,
ctrls: new Controls(overlay.g2, controls),
};
ui.ctrls.draw(ui.overlay.g2);
};
const terminateUI = () => {
state = State.Idle;
ui?.overlay.hide();
ui = undefined;
};
const onSwipe = () => {
switch (state) {
case State.Idle:
case State.IgnoreCurrent:
return;
case State.TopDrag:
case State.Active:
E.stopEventPropagation?.();
}
};
Bangle.prependListener('swipe', onSwipe);
const onDrag = (e => {
const dragDistance = 30;
if (e.b === 0) touchDown = startedUpDrag = false;
switch (state) {
case State.IgnoreCurrent:
if(e.b === 0)
state = State.Idle;
break;
case State.Idle:
if(e.b && !touchDown){ // no need to check Bangle.CLKINFO_FOCUS
if(e.y <= 40){
state = State.TopDrag
startY = e.y;
E.stopEventPropagation?.();
//console.log(" topdrag detected, starting @ " + startY);
}else{
//console.log(" ignoring this drag (too low @ " + e.y + ")");
state = State.IgnoreCurrent;
}
}
break;
case State.TopDrag:
if(e.b === 0){
//console.log("topdrag stopped, distance: " + (e.y - startY));
if(e.y > startY + dragDistance){
//console.log("activating");
initUI();
state = State.Active;
startY = 0;
Bangle.prependListener("touch", onTouch);
Bangle.buzz(20);
ui!.overlay.setBottom(g.getHeight());
}else{
//console.log("returning to idle");
terminateUI();
break; // skip stopEventPropagation
}
}else{
// partial drag, show UI feedback:
const dragOffset = 32;
initUI();
ui!.overlay.setBottom(e.y - dragOffset);
}
E.stopEventPropagation?.();
break;
case State.Active:
//console.log("stolen drag handling, do whatever here");
E.stopEventPropagation?.();
if(e.b){
if(!touchDown){
startY = e.y;
}else if(startY){
const dist = Math.max(0, startY - e.y);
if (startedUpDrag || (startedUpDrag = dist > 10)) // ignore small drags
ui!.overlay.setBottom(g.getHeight() - dist);
}
}else if(e.b === 0){
if((startY - e.y) > dragDistance){
let bottom = g.getHeight() - Math.max(0, startY - e.y);
if (upDragAnim) clearInterval(upDragAnim);
upDragAnim = setInterval(() => {
if (!ui || bottom <= 0) {
clearInterval(upDragAnim!);
upDragAnim = undefined;
terminateUI();
return;
}
ui.overlay.setBottom(bottom);
bottom -= 30;
}, 50)
Bangle.removeListener("touch", onTouch);
state = State.Idle;
}else{
ui!.overlay.setBottom(g.getHeight());
}
}
break;
}
if(e.b) touchDown = true;
}) satisfies DragCallback;
const onTouch = ((_btn, xy) => {
if(!ui || !xy) return;
const top = g.getHeight() - ui.overlay.height; // assumed anchored to bottom
const left = (g.getWidth() - ui.overlay.width) / 2; // more assumptions
const ctrl = ui.ctrls.hitTest(xy.x - left, xy.y - top);
if(ctrl){
onCtrlTap(ctrl, ui);
E.stopEventPropagation?.();
}
}) satisfies TouchCallback;
let origBuzz: undefined | (() => Promise<void>);
const onCtrlTap = (ctrl: Control, ui: UI) => {
Bangle.buzz(20);
const col = ctrl.cb(true) ? colour.on : colour.off;
ctrl.fg = col.fg;
ctrl.bg = col.bg;
//console.log("hit on " + ctrl.text + ", col: " + ctrl.fg);
ui.ctrls.draw(ui.overlay.g2, ctrl);
};
Bangle.prependListener("drag", onDrag);
Bangle.on("lock", terminateUI);
/*
const settings = require("Storage").readJSON("setting.json", true) as Settings || ({ HID: false } as Settings);
const haveMedia = settings.HID === "kbmedia";
// @ts-ignore
delete settings;
const sendHid = (code: number) => {
try{
NRF.sendHIDReport(
[1, code],
() => NRF.sendHIDReport([1, 0]),
);
}catch(e){
console.log("sendHIDReport:", e);
}
};
const hid = haveMedia ? {
next: () => sendHid(0x01),
prev: () => sendHid(0x02),
toggle: () => sendHid(0x10),
up: () => sendHid(0x40),
down: () => sendHid(0x80),
} : null;
*/
})()

View File

@ -0,0 +1,16 @@
{
"id": "ctrlpad",
"name": "Control Panel",
"shortName": "ctrlpad",
"version": "0.01",
"description": "Fast access (via a downward swipe) to common functions, such as bluetooth/HRM power and Do Not Disturb",
"icon": "icon.png",
"readme": "README.md",
"type": "bootloader",
"tags": "bluetooth",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"ctrlpad.boot.js","url":"main.js"},
{"name":"ctrlpad.img","url":"icon.js","evaluate":true}
]
}

View File

@ -11,6 +11,8 @@
// "checkJs": true,
// "noEmit": true,
"ignoreDeprecations": "5.0",
// code-gen
"declaration": false,
"emitDeclarationOnly": false,

View File

@ -11,7 +11,7 @@
"node-fetch": "^3.2.10"
},
"devDependencies": {
"typescript": "4.9.4"
"typescript": "^5.4.5"
}
},
"node_modules/data-uri-to-buffer": {
@ -91,16 +91,16 @@
}
},
"node_modules/typescript": {
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
"node": ">=14.17"
}
},
"node_modules/web-streams-polyfill": {
@ -151,9 +151,9 @@
}
},
"typescript": {
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"dev": true
},
"web-streams-polyfill": {

View File

@ -4,7 +4,7 @@
"author": "Sebastian Di Luzio <sebastian@diluz.io> (https://diluz.io), qucchia <qucchia0@gmail.com> (https://github.com/qucchia) and Rob Pilling (https://github.com/bobrippling)",
"version": "0.0.1",
"devDependencies": {
"typescript": "4.9.4"
"typescript": "^5.4.5"
},
"scripts": {
"build": "tsc"

View File

@ -1129,7 +1129,7 @@ declare class NRF {
* advertise battery level and its name as well as both Eddystone and iBeacon :
* ```
* NRF.setAdvertising([
* {0x180F : [Puck.getBatteryPercentage()]}, // normal advertising, with battery %
* {0x180F : [E.getBattery()]}, // normal advertising, with battery %
* require("ble_ibeacon").get(...), // iBeacon
* require("ble_eddystone").get(...), // eddystone
* ], {interval:300});
@ -1880,10 +1880,19 @@ declare class NRF {
* * `active` - whether to perform active scanning (requesting 'scan response'
* packets from any devices that are found). e.g. `NRF.requestDevice({ active:true,
* filters: [ ... ] })`
* * `phy` - (NRF52833/NRF52840 only) use the long-range coded phy (`"1mbps"` default, can
* be `"1mbps/2mbps/both/coded"`)
* * `phy` - (NRF52833/NRF52840 only) the type of Bluetooth signals to scan for (can
* be `"1mbps/coded/both/2mbps"`)
* * `1mbps` (default) - standard Bluetooth LE advertising
* * `coded` - long range
* * `both` - standard and long range
* * `2mbps` - high speed 2mbps (not working)
* * `extended` - (NRF52833/NRF52840 only) support receiving extended-length advertising
* packets (default=true if phy isn't `"1mbps"`)
* * `extended` - (NRF52833/NRF52840 only) support receiving extended-length advertising
* packets (default=true if phy isn't `"1mbps"`)
* * `window` - (2v22+) how long we scan for in milliseconds (default 100ms)
* * `interval` - (2v22+) how often we scan in milliseconds (default 100ms) - `window=interval=100`(default) is all the time. When
* scanning on both `1mbps` and `coded`, `interval` needs to be twice `window`.
* **NOTE:** `timeout` and `active` are not part of the Web Bluetooth standard.
* The following filter types are implemented:
* * `services` - list of services as strings (all of which must match). 128 bit
@ -2225,7 +2234,7 @@ declare class AES {
*/
declare class Pixl {
/**
* DEPRECATED - Please use `E.getBattery()` instead.
* **DEPRECATED** - Please use `E.getBattery()` instead.
* Return an approximate battery percentage remaining based on a normal CR2032
* battery (2.8 - 2.2v)
* @returns {number} A percentage between 0 and 100
@ -3249,25 +3258,44 @@ declare class Puck {
* Check out [the Puck.js page on the
* magnetometer](http://www.espruino.com/Puck.js#on-board-peripherals) for more
* information.
* ```JS
* Puck.magOn(10); // 10 Hz
* Puck.on('mag', function(e) {
* print(e);
* });
* // { "x": -874, "y": -332, "z": -1938 }
* ```
* @param {string} event - The event to listen to.
* @param {() => void} callback - A function that is executed when the event occurs.
* @param {(xyz: any) => void} callback - A function that is executed when the event occurs. Its arguments are:
* * `xyz` an object of the form `{x,y,z}`
* @url http://www.espruino.com/Reference#l_Puck_mag
*/
static on(event: "mag", callback: () => void): void;
static on(event: "mag", callback: (xyz: any) => void): void;
/**
* Only on Puck.js v2.0
* Called after `Puck.accelOn()` every time accelerometer data is sampled. There is
* one argument which is an object of the form `{acc:{x,y,z}, gyro:{x,y,z}}`
* containing the data.
* ```JS
* Puck.accelOn(12.5); // default 12.5Hz
* Puck.on('accel', function(e) {
* print(e);
* });
* //{
* // "acc": { "x": -525, "y": -112, "z": 8160 },
* // "gyro": { "x": 154, "y": -152, "z": -34 }
* //}
* ```
* The data is as it comes off the accelerometer and is not scaled to 1g. For more
* information see `Puck.accel()` or [the Puck.js page on the
* magnetometer](http://www.espruino.com/Puck.js#on-board-peripherals).
* @param {string} event - The event to listen to.
* @param {() => void} callback - A function that is executed when the event occurs.
* @param {(e: any) => void} callback - A function that is executed when the event occurs. Its arguments are:
* * `e` an object of the form `{acc:{x,y,z}, gyro:{x,y,z}}`
* @url http://www.espruino.com/Reference#l_Puck_accel
*/
static on(event: "accel", callback: () => void): void;
static on(event: "accel", callback: (e: any) => void): void;
/**
* Turn the magnetometer on and start periodic sampling. Samples will then cause a
@ -3472,7 +3500,7 @@ declare class Puck {
static light(): number;
/**
* DEPRECATED - Please use `E.getBattery()` instead.
* **DEPRECATED** - Please use `E.getBattery()` instead.
* Return an approximate battery percentage remaining based on a normal CR2032
* battery (2.8 - 2.2v).
* @returns {number} A percentage between 0 and 100
@ -3503,7 +3531,7 @@ declare class Puck {
*/
declare class Jolt {
/**
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET connected to GND.
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET (`Jolt.Q0.fet`) which switches GND.
* The `sda` and `scl` pins on this port are also analog inputs - use `analogRead(Jolt.Q0.sda)`/etc
* To turn this connector on run `Jolt.Q0.setPower(1)`
* @returns {any} An object containing the pins for the Q0 connector on Jolt.js `{sda,scl,fet}`
@ -3512,7 +3540,7 @@ declare class Jolt {
static Q0: Qwiic;
/**
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET connected to GND.
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET (`Jolt.Q1.fet`) which switches GND.
* The `sda` and `scl` pins on this port are also analog inputs - use `analogRead(Jolt.Q1.sda)`/etc
* To turn this connector on run `Jolt.Q1.setPower(1)`
* @returns {any} An object containing the pins for the Q1 connector on Jolt.js `{sda,scl,fet}`
@ -3540,23 +3568,26 @@ declare class Jolt {
/**
* Sets the mode of the motor drivers. Jolt.js has two motor drivers,
* one (`0`) for outputs 0..3, and one (`1`) for outputs 4..7. They
* one (`0`) for outputs H0..H3, and one (`1`) for outputs H4..H7. They
* can be controlled independently.
* Mode can be:
* * `undefined` / `false` / `"off"` - the motor driver is off, all motor driver pins are open circuit
* * `true` / `"output"` - **[recommended]** driver is set to "Independent bridge" mode. All 4 outputs are enabled and are either
* * `"motor"` - driver is set to "4 pin interface" mode where pins are paired up (V0+V1, V2+V3, etc). If both
* * `undefined` / `false` / `"off"` - the motor driver is off, all motor driver pins are open circuit (the motor driver still has a ~2.5k pulldown to GND)
* * `"auto"` - (default) - if any pin in the set of 4 pins (H0..H3, H4..H7) is set as an output, the driver is turned on. Eg `H0.set()` will
* turn the driver on with a high output, `H0.reset()` will pull the output to GND and `H0.read()` (or `H0.mode("input")` to set the state explicitly) is needed to
* turn the motor driver off.
* * `true` / `"output"` - **[recommended]** driver is set to "Independent bridge" mode. All 4 outputs in the bank are enabled
* * `"motor"` - driver is set to "4 pin interface" mode where pins are paired up (H0+H1, H2+H3, etc). If both
* in a pair are 0 the output is open circuit (motor coast), if both are 1 both otputs are 0 (motor brake), and
* if both are different, those values are on the output:
* `output` mode:
* | V0 | V1 | Out 0 | Out 1 |
* `output`/`auto` mode:
* | H0 | H1 | Out 0 | Out 1 |
* |----|----|-------|-------|
* | 0 | 0 | Low | Low |
* | 0 | 1 | Low | High |
* | 1 | 0 | High | Low |
* | 1 | 1 | High | High |
* `motor` mode
* | V0 | V1 | Out 0 | Out 1 |
* | H0 | H1 | Out 0 | Out 1 |
* |----|----|-------|-------|
* | 0 | 0 | Open | Open |
* | 0 | 1 | Low | High |
@ -4195,6 +4226,8 @@ declare class Bangle {
* * `hrmPushEnv` - (Bangle.js 2, 2v19+) if true (default is false) HRM environment readings will be produced as `Bangle.on(`HRM-env`, ...)` events. This is reset when the HRM is initialised with `Bangle.setHRMPower`.
* * `seaLevelPressure` (Bangle.js 2) Normally 1013.25 millibars - this is used for
* calculating altitude with the pressure sensor
* * `lcdBufferPtr` (Bangle.js 2 2v21+) Return a pointer to the first pixel of the 3 bit graphics buffer used by Bangle.js for the screen (stride = 178 bytes)
* * `lcdDoubleRefresh` (Bangle.js 2 2v22+) If enabled, pulses EXTCOMIN twice per poll interval (avoids off-axis flicker)
* Where accelerations are used they are in internal units, where `8192 = 1g`
*
* @param {any} options
@ -4530,11 +4563,11 @@ declare class Bangle {
* Read temperature, pressure and altitude data. A promise is returned which will
* be resolved with `{temperature, pressure, altitude}`.
* If the Barometer has been turned on with `Bangle.setBarometerPower` then this
* will return almost immediately with the reading. If the Barometer is off,
* will return with the *next* reading as of 2v21 (or the existing reading on 2v20 or earlier). If the Barometer is off,
* conversions take between 500-750ms.
* Altitude assumes a sea-level pressure of 1013.25 hPa
* If there's no pressure device (for example, the emulator),
* this returns undefined, rather than a promise.
* this returns `undefined`, rather than a Promise.
* ```
* Bangle.getPressure().then(d=>{
* console.log(d);
@ -4705,24 +4738,14 @@ declare class Bangle {
* While you could use setWatch/etc manually, the benefit here is that you don't
* end up with multiple `setWatch` instances, and the actual input method (touch,
* or buttons) is implemented dependent on the watch (Bangle.js 1 or 2)
* **Note:** You can override this function in boot code to change the interaction
* mode with the watch. For instance you could make all clocks start the launcher
* with a swipe by using:
* ```
* (function() {
* var sui = Bangle.setUI;
* Bangle.setUI = function(mode, cb) {
* var m = ("object"==typeof mode) ? mode.mode : mode;
* if (m!="clock") return sui(mode,cb);
* sui(); // clear
* Bangle.CLOCK=1;
* Bangle.swipeHandler = Bangle.showLauncher;
* Bangle.on("swipe", Bangle.swipeHandler);
* };
* })();
* Bangle.setUI("updown", function (dir) {
* // dir is +/- 1 for swipes up/down
* // dir is 0 when button pressed
* });
* ```
* The first argument can also be an object, in which case more options can be
* specified:
* specified with `mode:"custom"`:
* ```
* Bangle.setUI({
* mode : "custom",
@ -4740,7 +4763,23 @@ declare class Bangle {
* may choose to just call the `remove` function and then load a new app without resetting Bangle.js.
* As a result, **if you specify 'remove' you should make sure you test that after calling `Bangle.setUI()`
* without arguments your app is completely unloaded**, otherwise you may end up with memory leaks or
* other issues when switching apps. Please see http://www.espruino.com/Bangle.js+Fast+Load for more details on this.
* other issues when switching apps. Please see the [Bangle.js Fast Load Tutorial](https://www.espruino.com/Bangle.js+Fast+Load) for more details on this.
* **Note:** You can override this function in boot code to change the interaction
* mode with the watch. For instance you could make all clocks start the launcher
* with a swipe by using:
* ```
* (function() {
* var sui = Bangle.setUI;
* Bangle.setUI = function(mode, cb) {
* var m = ("object"==typeof mode) ? mode.mode : mode;
* if (m!="clock") return sui(mode,cb);
* sui(); // clear
* Bangle.CLOCK=1;
* Bangle.swipeHandler = Bangle.showLauncher;
* Bangle.on("swipe", Bangle.swipeHandler);
* };
* })();
* ```
*
* @param {any} type - The type of UI input: 'updown', 'leftright', 'clock', 'clockupdown' or undefined to cancel. Can also be an object (see below)
* @param {any} callback - A function with one argument which is the direction
@ -4795,6 +4834,7 @@ declare class Badge {
static capSense(corner: number): number;
/**
* **DEPRECATED** - Please use `E.getBattery()` instead.
* Return an approximate battery percentage remaining based on a normal CR2032
* battery (2.8 - 2.2v)
* @returns {number} A percentage between 0 and 100
@ -5401,11 +5441,11 @@ declare class Graphics<IsBuffer extends boolean = boolean> {
/**
* Set the current font
*
* @param {number} [scale] - [optional] If >1 the font will be scaled up by that amount
* @param {number} scale - (optional) If >1 the font will be scaled up by that amount
* @returns {any} The instance of Graphics this was called on, to allow call chaining
* @url http://www.espruino.com/Reference#l_Graphics_setFont6x15
*/
setFont6x15(scale?: number): Graphics;
setFont6x15(scale: number): Graphics;
/**
* On instances of graphics that drive a display with an offscreen buffer, calling
@ -5775,10 +5815,11 @@ declare class Graphics<IsBuffer extends boolean = boolean> {
/**
*
* @param {any} file - The font as a PBF file
* @param {number} scale - The scale factor, default=1 (2=2x size)
* @returns {any} The instance of Graphics this was called on, to allow call chaining
* @url http://www.espruino.com/Reference#l_Graphics_setFontPBF
*/
setFontPBF(file: any): Graphics;
setFontPBF(file: any, scale: number): Graphics;
/**
* Set the alignment for subsequent calls to `drawString`
@ -7492,12 +7533,12 @@ interface Date {
/**
* Month of the year 0..11
*
* @param {number} yearValue - The month, between 0 and 11
* @param {number} monthValue - The month, between 0 and 11
* @param {any} [dayValue] - [optional] the day, between 0 and 31
* @returns {number} The number of milliseconds since 1970
* @url http://www.espruino.com/Reference#l_Date_setMonth
*/
setMonth(yearValue: number, dayValue?: number): number;
setMonth(monthValue: number, dayValue?: number): number;
/**
*
@ -7863,6 +7904,7 @@ declare class E {
* "A Number" : {
* value : number,
* min:0,max:100,step:10,
* // noList : true, // On Bangle.js devices this forces use of the number-chooser (and not a scrolling list)
* onchange : v => { number=v; }
* },
* "Exit" : function() { E.showMenu(); }, // remove the menu
@ -8415,19 +8457,27 @@ declare class E {
static getAnalogVRef(): number;
/**
* ADVANCED: This is a great way to crash Espruino if you're not sure what you are
* doing
* ADVANCED: It's very easy to crash Espruino using this function if
* you get the code/arguments you supply wrong!
* Create a native function that executes the code at the given address, e.g.
* `E.nativeCall(0x08012345,'double (double,double)')(1.1, 2.2)`
* If you're executing a thumb function, you'll almost certainly need to set the
* bottom bit of the address to 1.
* Note it's not guaranteed that the call signature you provide can be used - there
* are limits on the number of arguments allowed.
* are limits on the number of arguments allowed (5).
* When supplying `data`, if it is a 'flat string' then it will be used directly,
* otherwise it'll be converted to a flat string and used.
* The argument types in `sig` are:
* * `void` - returns nothing
* * `bool` - boolean value
* * `int` - 32 bit integer
* * `double` - 64 bit floating point
* * `float` - 32 bit floating point (2v21 and later)
* * `Pin` - Espruino 'pin' value (8 bit integer)
* * `JsVar` - Pointer to an Espruino JsVar structure
*
* @param {number} addr - The address in memory of the function (or offset in `data` if it was supplied
* @param {any} sig - The signature of the call, `returnType (arg1,arg2,...)`. Allowed types are `void`,`bool`,`int`,`double`,`Pin`,`JsVar`
* @param {any} sig - The signature of the call, `returnType (arg1,arg2,...)`. Allowed types are `void`,`bool`,`int`,`double`,`float`,`Pin`,`JsVar`
* @param {any} data - (Optional) A string containing the function itself. If not supplied then 'addr' is used as an absolute address.
* @returns {any} The native function
* @url http://www.espruino.com/Reference#l_E_nativeCall
@ -8777,12 +8827,11 @@ declare class E {
static toJS(arg: any): string;
/**
* This creates and returns a special type of string, which actually references a
* specific memory address. It can be used in order to use sections of Flash memory
* directly in Espruino (for example to execute code straight from flash memory
* with `eval(E.memoryArea( ... ))`)
* **Note:** This is only tested on STM32-based platforms (Espruino Original and
* Espruino Pico) at the moment.
* This creates and returns a special type of string, which references a
* specific address in memory. It can be used in order to use sections of
* Flash memory directly in Espruino (for example `Storage` uses it
* to allow files to be read directly from Flash).
* **Note:** As of 2v21, Calling `E.memoryArea` with an address of 0 will return `undefined`
*
* @param {number} addr - The address of the memory area
* @param {number} len - The length (in bytes) of the memory area
@ -9313,6 +9362,35 @@ declare class E {
*/
static getRTCPrescaler(calibrate: boolean): number;
/**
* This function returns an object detailing the current **estimated** power usage
* of the Espruino device in microamps (uA). It is not intended to be a replacement
* for measuring actual power consumption, but can be useful for finding obvious power
* draws.
* Where an Espruino device has outputs that are connected to other things, those
* are not included in the power usage figures.
* Results look like:
* ```
* {
* device: {
* CPU : 2000, // microcontroller
* LCD : 100, // LCD
* // ...
* },
* total : 5500 // estimated usage in microamps
* }
* ```
* **Note:** Currently only nRF52-based devices have variable CPU power usage
* figures. These are based on the time passed for each SysTick event, so under heavy
* usage the figure will update within 0.3s, but under low CPU usage it could take
* minutes for the CPU usage figure to update.
* **Note:** On Jolt.js we take account of internal resistance on H0/H2/H4/H6 where
* we can measure voltage. H1/H3/H5/H7 cannot be measured.
* @returns {any} An object detailing power usage in microamps
* @url http://www.espruino.com/Reference#l_E_getPowerUsage
*/
static getPowerUsage(): any;
/**
* Decode a UTF8 string.
* * Any decoded character less than 256 gets passed straight through
@ -10828,6 +10906,85 @@ declare class Serial {
flush(): void;
}
/**
* (2v21+ only) This class allows Espruino to control stepper motors.
* ```
* // initialise
* var s = new Stepper({
* pins : [D1,D0,D2,D3],
* freq : 200
* });
* // step 1000 steps...
* s.moveTo(1000, {turnOff:true}).then(() => {
* print("Done!");
* });
* ```
* On Espruino before 2v20 you can still use the Stepper Motor module at https://www.espruino.com/StepperMotor - it just isn't quite as fast.
* @url http://www.espruino.com/Reference#Stepper
*/
declare class Stepper {
/**
* Create a `Stepper` class. `options` can contain:
* ```
* ... = new Stepper({
* pins : [...], // required - 4 element array of pins
* pattern : [...], // optional - a 4/8 element array of step patterns
* offpattern : 0, // optional (default 0) - the pattern to output to stop driving the stepper motor
* freq : 500, // optional (default 100) steps per second
* })
* ```
* `pins` must be supplied as a 4 element array of pins. When created,
* if pin state has not been set manually on each pin, the pins will
* be set to outputs.
* If `pattern` isn't specified, a default pattern of `[0b0001,0b0010,0b0100,0b1000]` will be used. You
* can specify different patterns, for example `[0b1100,0b1000,0b1001,0b0001,0b0011,0b0010,0b0110,0b0100]`.
* @constructor
*
* @param {any} options - options struct `{pins:[1,2,3,4]}`
* @returns {any} An Stepper object
* @url http://www.espruino.com/Reference#l_Stepper_Stepper
*/
static new(options: any): any;
/**
* Move a a certain number of steps in either direction. `position` is remembered, so
* `s.moveTo(1000)` will move 1000 steps forward the first time it is called, but
* `s.moveTo(1500)` called afterwards will only move 500 steps.
* , `options` can be:
* ```
* s.moveTo(steps, {
* freq : 100, // optional (frequency in Hz) step frequency
* turnOff : true, // optional (default false) turn off stepper after this movement?
* relative : true, // optional (default false) the step number is relative (not absolute)
* }).then(() => {
* // movement finished...
* });
* ```
*
* @param {number} position - The position in steps to move to (can be either positive or negative)
* @param {any} options - Optional options struct
* @returns {any} A Promise that resolves when the stepper has finished moving
* @url http://www.espruino.com/Reference#l_Stepper_moveTo
*/
moveTo(position: number, options: any): Promise<void>;
/**
* Stop a stepper motor that is currently running.
* You can specify `.stop({turnOff:true})` to force the stepper motor to turn off.
*
* @param {any} options - Optional options struct
* @url http://www.espruino.com/Reference#l_Stepper_stop
*/
stop(options: any): void;
/**
* Get the current position of the stepper motor in steps
* @returns {number} The current position of the stepper motor in steps
* @url http://www.espruino.com/Reference#l_Stepper_getPosition
*/
getPosition(): number;
}
interface StringConstructor {
/**
* Return the character(s) represented by the given character code(s).
@ -10927,16 +11084,26 @@ interface String {
/**
* Search and replace ONE occurrence of `subStr` with `newSubStr` and return the
* result. This doesn't alter the original string. Regular expressions not
* supported.
* result. This doesn't alter the original string.
*
* @param {any} subStr - The string to search for
* @param {any} newSubStr - The string to replace it with
* @param {any} subStr - The string (or Regular Expression) to search for
* @param {any} newSubStr - The string to replace it with. Replacer functions are supported, but only when subStr is a `RegExp`
* @returns {any} This string with `subStr` replaced
* @url http://www.espruino.com/Reference#l_String_replace
*/
replace(subStr: any, newSubStr: any): any;
/**
* Search and replace ALL occurrences of `subStr` with `newSubStr` and return the
* result. This doesn't alter the original string.
*
* @param {any} subStr - The string (or Regular Expression) to search for
* @param {any} newSubStr - The string to replace it with. Replacer functions are supported, but only when subStr is a `RegExp`
* @returns {any} This string with `subStr` replaced
* @url http://www.espruino.com/Reference#l_String_replaceAll
*/
replaceAll(subStr: any, newSubStr: any): any;
/**
*
* @param {number} start - The start character index (inclusive)
@ -10991,6 +11158,9 @@ interface String {
toUpperCase(): any;
/**
* This is not a standard JavaScript function, but is provided to allow use of fonts
* that only support ASCII (char codes 0..127, like the 4x6 font) with character input
* that might be in the ISO8859-1 range.
* @returns {any} This string with the accents/diacritics (such as é, ü) removed from characters in the ISO 8859-1 set
* @url http://www.espruino.com/Reference#l_String_removeAccents
*/
@ -11454,6 +11624,42 @@ declare function compass(): any;
*/
declare const FET: Pin;
/**
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET (`Q0.fet`) which switches GND.
* The `sda` and `scl` pins on this port are also analog inputs - use `analogRead(Q0.sda)`/etc
* To turn this connector on run `Q0.setPower(1)`
* @returns {any} An object containing the pins for the Q0 connector on Jolt.js `{sda,scl,fet}`
* @url http://www.espruino.com/Reference#l__global_Q0
*/
declare const Q0: Qwiic;
/**
* `Q0` and `Q1` Qwiic connectors can have their power controlled by a 500mA FET (`Q1.fet`) which switches GND.
* The `sda` and `scl` pins on this port are also analog inputs - use `analogRead(Q1.sda)`/etc
* To turn this connector on run `Q1.setPower(1)`
* @returns {any} An object containing the pins for the Q1 connector on Jolt.js `{sda,scl,fet}`
* @url http://www.espruino.com/Reference#l__global_Q1
*/
declare const Q1: Qwiic;
/**
* `Q2` and `Q3` have all 4 pins connected to Jolt.js's GPIO (including those usually used for power).
* As such only around 8mA of power can be supplied to any connected device.
* To use this as a normal Qwiic connector, run `Q2.setPower(1)`
* @returns {any} An object containing the pins for the Q2 connector on Jolt.js `{sda,scl,gnd,vcc}`
* @url http://www.espruino.com/Reference#l__global_Q2
*/
declare const Q2: Qwiic;
/**
* `Q2` and `Q3` have all 4 pins connected to Jolt.js's GPIO (including those usually used for power).
* As such only around 8mA of power can be supplied to any connected device.
* To use this as a normal Qwiic connector, run `Q3.setPower(1)`
* @returns {any} An object containing the pins for the Q3 connector on Jolt.js `{sda,scl,gnd,vcc}`
* @url http://www.espruino.com/Reference#l__global_Q3
*/
declare const Q3: Qwiic;
/**
* The Bangle.js's vibration motor.
* @returns {Pin}
@ -11641,110 +11847,6 @@ declare const IOEXT3: Pin;
*/
declare const Terminal: Serial;
declare const global: {
SDA: typeof SDA;
SCL: typeof SCL;
show: typeof show;
acceleration: typeof acceleration;
compass: typeof compass;
FET: typeof FET;
VIBRATE: typeof VIBRATE;
LED: typeof LED;
LED1: typeof LED1;
LED2: typeof LED2;
BTNA: typeof BTNA;
BTNB: typeof BTNB;
BTNU: typeof BTNU;
BTND: typeof BTND;
BTNL: typeof BTNL;
BTNR: typeof BTNR;
CORNER1: typeof CORNER1;
CORNER2: typeof CORNER2;
CORNER3: typeof CORNER3;
CORNER4: typeof CORNER4;
CORNER5: typeof CORNER5;
CORNER6: typeof CORNER6;
Bluetooth: typeof Bluetooth;
MOS1: typeof MOS1;
MOS2: typeof MOS2;
MOS3: typeof MOS3;
MOS4: typeof MOS4;
IOEXT0: typeof IOEXT0;
IOEXT1: typeof IOEXT1;
IOEXT2: typeof IOEXT2;
IOEXT3: typeof IOEXT3;
Terminal: typeof Terminal;
global: typeof global;
setBusyIndicator: typeof setBusyIndicator;
setSleepIndicator: typeof setSleepIndicator;
setDeepSleep: typeof setDeepSleep;
dump: typeof dump;
load: typeof load;
save: typeof save;
reset: typeof reset;
edit: typeof edit;
echo: typeof echo;
getTime: typeof getTime;
setTime: typeof setTime;
getSerial: typeof getSerial;
setInterval: typeof setInterval;
setTimeout: typeof setTimeout;
clearInterval: typeof clearInterval;
clearTimeout: typeof clearTimeout;
changeInterval: typeof changeInterval;
peek8: typeof peek8;
poke8: typeof poke8;
peek16: typeof peek16;
poke16: typeof poke16;
peek32: typeof peek32;
poke32: typeof poke32;
analogRead: typeof analogRead;
analogWrite: typeof analogWrite;
digitalPulse: typeof digitalPulse;
digitalWrite: typeof digitalWrite;
digitalRead: typeof digitalRead;
pinMode: typeof pinMode;
getPinMode: typeof getPinMode;
shiftOut: typeof shiftOut;
setWatch: typeof setWatch;
clearWatch: typeof clearWatch;
arguments: typeof arguments;
eval: typeof eval;
parseInt: typeof parseInt;
parseFloat: typeof parseFloat;
isFinite: typeof isFinite;
isNaN: typeof isNaN;
btoa: typeof btoa;
atob: typeof atob;
encodeURIComponent: typeof encodeURIComponent;
decodeURIComponent: typeof decodeURIComponent;
trace: typeof trace;
print: typeof print;
require: typeof require;
__FILE__: typeof __FILE__;
SPI1: typeof SPI1;
SPI2: typeof SPI2;
SPI3: typeof SPI3;
I2C1: typeof I2C1;
I2C2: typeof I2C2;
I2C3: typeof I2C3;
USB: typeof USB;
Serial1: typeof Serial1;
Serial2: typeof Serial2;
Serial3: typeof Serial3;
Serial4: typeof Serial4;
Serial5: typeof Serial5;
Serial6: typeof Serial6;
LoopbackA: typeof LoopbackA;
LoopbackB: typeof LoopbackB;
Telnet: typeof Telnet;
NaN: typeof NaN;
Infinity: typeof Infinity;
HIGH: typeof HIGH;
LOW: typeof LOW;
[key: string]: any;
}
/**
* When Espruino is busy, set the pin specified here high. Set this to undefined to
* disable the feature.
@ -12072,16 +12174,19 @@ declare function peek32(addr: number, count: number): Uint8Array;
declare function poke32(addr: number, value: number | number[]): void;
/**
* Get the analogue value of the given pin
* Get the analogue value of the given pin.
* This is different to Arduino which only returns an integer between 0 and 1023
* However only pins connected to an ADC will work (see the datasheet)
* **Note:** if you didn't call `pinMode` beforehand then this function will also
* reset pin's state to `"analog"`
* **Note:** if you didn't call `pinMode` beforehand then this function will also
* reset pin's state to `"analog"`
* **Note:** [Jolt.js](https://www.espruino.com/Jolt.js) motor driver pins with
* analog inputs are scaled with a potential divider, and so those pins return a
* number which is the actual voltage.
*
* @param {Pin} pin
* The pin to use
* You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `ADC` markers.
* @returns {number} The analog Value of the Pin between 0 and 1
* @returns {number} The Analog Value of the Pin between 0(GND) and 1(VCC). See below.
* @url http://www.espruino.com/Reference#l__global_analogRead
*/
declare function analogRead(pin: Pin): number;
@ -12132,8 +12237,12 @@ declare function digitalPulse(pin: Pin, value: boolean, time: number | number[])
/**
* Set the digital value of the given pin.
* **Note:** if you didn't call `pinMode` beforehand then this function will also
* reset pin's state to `"output"`
* ```
* digitalWrite(LED1, 1); // light LED1
* digitalWrite([LED1,LED2,LED3], 0b101); // lights LED1 and LED3
* ```
* **Note:** if you didn't call `pinMode(pin, ...)` or `Pin.mode(...)` beforehand then this function will also
* reset pin's state to `"output"`
* If pin argument is an array of pins (e.g. `[A2,A1,A0]`) the value argument will
* be treated as an array of bits where the last array element is the least
* significant bit.
@ -12141,11 +12250,15 @@ declare function digitalPulse(pin: Pin, value: boolean, time: number | number[])
* right-hand side of the array of pins). This means you can use the same pin
* multiple times, for example `digitalWrite([A1,A1,A0,A0],0b0101)` would pulse A0
* followed by A1.
* In 2v22 and later firmwares, using a boolean for the value will set *all* pins in
* the array to the same value, eg `digitalWrite(pins, value?0xFFFFFFFF:0)`. Previously
* digitalWrite with a boolean behaved like `digitalWrite(pins, value?1:0)` and would
* only set the first pin.
* If the pin argument is an object with a `write` method, the `write` method will
* be called with the value passed through.
*
* @param {any} pin - The pin to use
* @param {number} value - Whether to pulse high (true) or low (false)
* @param {any} value - Whether to write a high (true) or low (false) value
* @url http://www.espruino.com/Reference#l__global_digitalWrite
*/
declare function digitalWrite(pin: Pin, value: boolean): void;
@ -12316,6 +12429,123 @@ declare function setWatch(func: ((arg: { state: boolean, time: number, lastTime:
declare function clearWatch(id: number): void;
declare function clearWatch(): void;
declare const global: {
SDA: typeof SDA;
SCL: typeof SCL;
show: typeof show;
acceleration: typeof acceleration;
compass: typeof compass;
FET: typeof FET;
Q0: typeof Q0;
Q1: typeof Q1;
Q2: typeof Q2;
Q3: typeof Q3;
VIBRATE: typeof VIBRATE;
LED: typeof LED;
LED1: typeof LED1;
LED2: typeof LED2;
BTNA: typeof BTNA;
BTNB: typeof BTNB;
BTNU: typeof BTNU;
BTND: typeof BTND;
BTNL: typeof BTNL;
BTNR: typeof BTNR;
CORNER1: typeof CORNER1;
CORNER2: typeof CORNER2;
CORNER3: typeof CORNER3;
CORNER4: typeof CORNER4;
CORNER5: typeof CORNER5;
CORNER6: typeof CORNER6;
Bluetooth: typeof Bluetooth;
MOS1: typeof MOS1;
MOS2: typeof MOS2;
MOS3: typeof MOS3;
MOS4: typeof MOS4;
IOEXT0: typeof IOEXT0;
IOEXT1: typeof IOEXT1;
IOEXT2: typeof IOEXT2;
IOEXT3: typeof IOEXT3;
Terminal: typeof Terminal;
setBusyIndicator: typeof setBusyIndicator;
setSleepIndicator: typeof setSleepIndicator;
setDeepSleep: typeof setDeepSleep;
dump: typeof dump;
load: typeof load;
save: typeof save;
reset: typeof reset;
edit: typeof edit;
echo: typeof echo;
getTime: typeof getTime;
setTime: typeof setTime;
getSerial: typeof getSerial;
setInterval: typeof setInterval;
setTimeout: typeof setTimeout;
clearInterval: typeof clearInterval;
clearTimeout: typeof clearTimeout;
changeInterval: typeof changeInterval;
peek8: typeof peek8;
poke8: typeof poke8;
peek16: typeof peek16;
poke16: typeof poke16;
peek32: typeof peek32;
poke32: typeof poke32;
analogRead: typeof analogRead;
analogWrite: typeof analogWrite;
digitalPulse: typeof digitalPulse;
digitalWrite: typeof digitalWrite;
digitalRead: typeof digitalRead;
pinMode: typeof pinMode;
getPinMode: typeof getPinMode;
shiftOut: typeof shiftOut;
setWatch: typeof setWatch;
clearWatch: typeof clearWatch;
global: typeof global;
globalThis: typeof globalThis;
arguments: typeof arguments;
eval: typeof eval;
parseInt: typeof parseInt;
parseFloat: typeof parseFloat;
isFinite: typeof isFinite;
isNaN: typeof isNaN;
btoa: typeof btoa;
atob: typeof atob;
encodeURIComponent: typeof encodeURIComponent;
decodeURIComponent: typeof decodeURIComponent;
trace: typeof trace;
print: typeof print;
require: typeof require;
__FILE__: typeof __FILE__;
SPI1: typeof SPI1;
SPI2: typeof SPI2;
SPI3: typeof SPI3;
I2C1: typeof I2C1;
I2C2: typeof I2C2;
I2C3: typeof I2C3;
USB: typeof USB;
Serial1: typeof Serial1;
Serial2: typeof Serial2;
Serial3: typeof Serial3;
Serial4: typeof Serial4;
Serial5: typeof Serial5;
Serial6: typeof Serial6;
LoopbackA: typeof LoopbackA;
LoopbackB: typeof LoopbackB;
Telnet: typeof Telnet;
NaN: typeof NaN;
Infinity: typeof Infinity;
HIGH: typeof HIGH;
LOW: typeof LOW;
[key: string]: any;
}
/**
* A reference to the global scope, where everything is defined.
* This is identical to `global` but was introduced in the ECMAScript spec.
* @returns {any} The global scope
* @url http://www.espruino.com/Reference#l__global_globalThis
*/
// globalThis - builtin
/**
* A variable containing the arguments given to the function:
* ```