@typecad/hal 1.0.0-alpha.13 → 1.0.0-alpha.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -87
- package/dist/adc-pin.d.ts +53 -0
- package/dist/adc-pin.js +69 -0
- package/dist/async.d.ts +3 -11
- package/dist/async.js +3 -15
- package/dist/ble.d.ts +42 -78
- package/dist/ble.js +79 -98
- package/dist/counter.d.ts +16 -0
- package/dist/counter.js +32 -0
- package/dist/dac-pin.d.ts +13 -0
- package/dist/dac-pin.js +21 -0
- package/dist/emit.d.ts +123 -196
- package/dist/emit.js +146 -208
- package/dist/fs.d.ts +12 -31
- package/dist/fs.js +30 -40
- package/dist/gpio-pin.d.ts +46 -0
- package/dist/gpio-pin.js +77 -0
- package/dist/gpio.d.ts +0 -103
- package/dist/gpio.js +16 -227
- package/dist/http.d.ts +38 -39
- package/dist/http.js +53 -78
- package/dist/i2c-target.d.ts +28 -0
- package/dist/i2c-target.js +52 -0
- package/dist/i2c.d.ts +5 -43
- package/dist/i2c.js +17 -130
- package/dist/index.d.ts +30 -42
- package/dist/index.js +27 -39
- package/dist/math.d.ts +0 -13
- package/dist/math.js +9 -13
- package/dist/mqtt.d.ts +15 -25
- package/dist/mqtt.js +32 -28
- package/dist/power.d.ts +9 -17
- package/dist/power.js +22 -20
- package/dist/preferences.d.ts +17 -25
- package/dist/preferences.js +54 -52
- package/dist/pulse.d.ts +4 -4
- package/dist/pulse.js +6 -2
- package/dist/pwm-pin.d.ts +24 -0
- package/dist/pwm-pin.js +38 -0
- package/dist/random.d.ts +0 -2
- package/dist/random.js +14 -20
- package/dist/sensor-catalog.generated.d.ts +997 -0
- package/dist/sensor-catalog.generated.js +764 -0
- package/dist/sensor.d.ts +46 -0
- package/dist/sensor.js +52 -0
- package/dist/shift-pin.d.ts +2 -0
- package/dist/shift-pin.js +13 -0
- package/dist/spi-target.d.ts +25 -0
- package/dist/spi-target.js +42 -0
- package/dist/spi.d.ts +8 -26
- package/dist/spi.js +15 -87
- package/dist/thread.d.ts +18 -0
- package/dist/thread.js +36 -0
- package/dist/time.d.ts +23 -0
- package/dist/time.js +43 -0
- package/dist/timing.d.ts +17 -7
- package/dist/timing.js +17 -7
- package/dist/types.d.ts +4 -34
- package/dist/types.js +5 -47
- package/dist/uart-port.d.ts +26 -0
- package/dist/uart-port.js +52 -0
- package/dist/uart.d.ts +0 -17
- package/dist/uart.js +10 -53
- package/dist/usb.d.ts +26 -0
- package/dist/usb.js +66 -0
- package/dist/watchdog.d.ts +12 -0
- package/dist/watchdog.js +28 -0
- package/dist/wifi.d.ts +88 -64
- package/dist/wifi.js +112 -126
- package/dist/zephyr-tokens.generated.d.ts +8 -0
- package/dist/zephyr-tokens.generated.js +73 -0
- package/package.json +7 -8
- package/src/adc-pin.ts +89 -0
- package/src/async.ts +3 -16
- package/src/ble.ts +84 -111
- package/src/counter.ts +40 -0
- package/src/dac-pin.ts +28 -0
- package/src/emit.ts +157 -238
- package/src/fs.ts +47 -54
- package/src/gpio-pin.ts +91 -0
- package/src/gpio.ts +49 -320
- package/src/http.ts +75 -95
- package/src/i2c-target.ts +63 -0
- package/src/i2c.ts +29 -167
- package/src/index.ts +32 -46
- package/src/math.ts +9 -14
- package/src/mqtt.ts +39 -31
- package/src/preferences.ts +52 -61
- package/src/pwm-pin.ts +54 -0
- package/src/random.ts +14 -21
- package/src/sensor-catalog.generated.ts +1238 -0
- package/src/sensor.ts +80 -0
- package/src/shift-pin.ts +16 -0
- package/src/spi-target.ts +53 -0
- package/src/spi.ts +27 -121
- package/src/thread.ts +44 -0
- package/src/time.ts +50 -0
- package/src/types.ts +14 -89
- package/src/uart-port.ts +64 -0
- package/src/usb.ts +82 -0
- package/src/watchdog.ts +35 -0
- package/src/wifi.ts +147 -179
- package/src/zephyr-tokens.generated.ts +77 -0
- package/src/adc.ts +0 -30
- package/src/capacitive.ts +0 -31
- package/src/constants.ts +0 -23
- package/src/dac.ts +0 -21
- package/src/eeprom.ts +0 -26
- package/src/interrupts.ts +0 -35
- package/src/mdns.ts +0 -50
- package/src/ota.ts +0 -44
- package/src/power.ts +0 -36
- package/src/pulse.ts +0 -63
- package/src/rmt.ts +0 -125
- package/src/shift.ts +0 -88
- package/src/temperature.ts +0 -20
- package/src/timer.ts +0 -58
- package/src/timing.ts +0 -67
- package/src/uart.ts +0 -77
- package/src/utils.ts +0 -17
- package/src/wdt.ts +0 -17
package/src/gpio-pin.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// GPIO — the thin Zephyr-shaped digital pin class
|
|
3
|
+
//
|
|
4
|
+
// One configured pin handle ≈ gpio_dt_spec + flags, mirroring Zephyr's verbs:
|
|
5
|
+
// construction carries the flag combination (GPIO.OUTPUT | GPIO.PULL_UP),
|
|
6
|
+
// set/get/toggle lower to gpio_pin_set_dt / get_dt / toggle_dt (logical
|
|
7
|
+
// levels — polarity comes from the board's DT node when the pin has a dtSpec),
|
|
8
|
+
// and the configure itself is emitted guarded-per-pin ahead of the first use,
|
|
9
|
+
// so construction flags apply exactly once. No mode strings, no shadow reads.
|
|
10
|
+
//
|
|
11
|
+
// Flag and interrupt tokens are Zephyr's names under the GPIO. namespace
|
|
12
|
+
// (GPIO_OUTPUT ↔ GPIO.OUTPUT, GPIO_INT_EDGE_FALLING ↔ GPIO.INT_EDGE_FALLING);
|
|
13
|
+
// the lowering maps token NAMES to macros, so any Zephyr doc greps both ways.
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
import { gpioWrite, gpioReadCfg, gpioToggle, gpioConfigure, interruptAttachFlags, interruptDetach } from './emit.js';
|
|
17
|
+
import { callback } from './callback.js';
|
|
18
|
+
import type { Pin } from './gpio.js';
|
|
19
|
+
|
|
20
|
+
export class GPIO {
|
|
21
|
+
// ── Config flags (gpio.h) ──────────────────────────────────────────────
|
|
22
|
+
static readonly INPUT = 0x001;
|
|
23
|
+
static readonly OUTPUT = 0x002;
|
|
24
|
+
/** Configure the output buffer's initial level atomically — no
|
|
25
|
+
* configure-then-write glitch window. */
|
|
26
|
+
static readonly OUTPUT_INIT_LOW = 0x004;
|
|
27
|
+
static readonly OUTPUT_INIT_HIGH = 0x008;
|
|
28
|
+
static readonly PULL_UP = 0x010;
|
|
29
|
+
static readonly PULL_DOWN = 0x020;
|
|
30
|
+
static readonly OPEN_DRAIN = 0x040;
|
|
31
|
+
static readonly OPEN_SOURCE = 0x080;
|
|
32
|
+
static readonly DISCONNECTED = 0x100;
|
|
33
|
+
|
|
34
|
+
// ── Interrupt flags (GPIO_INT_* minus the prefix) ──────────────────────
|
|
35
|
+
static readonly INT_DISABLE = 0x01;
|
|
36
|
+
static readonly INT_EDGE_RISING = 0x02;
|
|
37
|
+
static readonly INT_EDGE_FALLING = 0x04;
|
|
38
|
+
static readonly INT_EDGE_BOTH = 0x08;
|
|
39
|
+
static readonly INT_LEVEL_LOW = 0x10;
|
|
40
|
+
static readonly INT_LEVEL_HIGH = 0x20;
|
|
41
|
+
|
|
42
|
+
private readonly _pin: number;
|
|
43
|
+
private readonly _flags: number;
|
|
44
|
+
|
|
45
|
+
/** Construct a configured pin. `flags` is a combination of the GPIO.*
|
|
46
|
+
* statics (the transpiler carries the token text; the values are for the
|
|
47
|
+
* editor only). The configure applies once, ahead of the first
|
|
48
|
+
* set/get/toggle/onInterrupt call. */
|
|
49
|
+
constructor(pin: number | Pin, flags: number) {
|
|
50
|
+
this._pin = typeof pin === 'number' ? pin : pin.number;
|
|
51
|
+
this._flags = flags;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Drive the pin (gpio_pin_set_dt / set_raw). Logical level: on a pin with
|
|
55
|
+
* a board dtSpec (LED, BUTTON), true means "active" — the DT node's
|
|
56
|
+
* GPIO_ACTIVE_LOW is honored. */
|
|
57
|
+
set(value: boolean): void {
|
|
58
|
+
gpioConfigure(this._pin, this._flags);
|
|
59
|
+
gpioWrite(this._pin, value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Read the pin (gpio_pin_get_dt / get_raw). Logical level. The guarded
|
|
63
|
+
* configure is FUSED into the read's lowering (one statement-expression),
|
|
64
|
+
* so the pin is correctly configured even when the call sits in a pure
|
|
65
|
+
* expression position (if-conditions, comparisons) where a method's
|
|
66
|
+
* leading side-effect ops would otherwise be dropped. */
|
|
67
|
+
get(): boolean {
|
|
68
|
+
return gpioReadCfg(this._pin, this._flags) as unknown as boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Toggle the pin (gpio_pin_toggle_dt — the driver's atomic toggle). */
|
|
72
|
+
toggle(): void {
|
|
73
|
+
gpioConfigure(this._pin, this._flags);
|
|
74
|
+
gpioToggle(this._pin);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Attach an interrupt (gpio_pin_interrupt_configure_dt +
|
|
78
|
+
* gpio_init_callback + gpio_add_callback). `intFlags` is one GPIO.INT_*
|
|
79
|
+
* token — Zephyr's names verbatim, covering the level modes the legacy
|
|
80
|
+
* onHigh/onLow strings could not express. */
|
|
81
|
+
onInterrupt(intFlags: number, handler: () => void): void {
|
|
82
|
+
gpioConfigure(this._pin, this._flags);
|
|
83
|
+
interruptAttachFlags(this._pin, callback(handler), intFlags);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Detach the interrupt (disable + remove callback). */
|
|
87
|
+
offInterrupt(): void {
|
|
88
|
+
interruptDetach(this._pin);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
package/src/gpio.ts
CHANGED
|
@@ -1,320 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
isLow(): boolean {
|
|
51
|
-
return !this.read();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
pulse(durationMs: number): void {
|
|
55
|
-
gpioWrite(this._pin, 1);
|
|
56
|
-
rawCpp(`delay(${durationMs});`);
|
|
57
|
-
gpioWrite(this._pin, 0);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
tone(frequency: number): ToneChain {
|
|
61
|
-
tonePlay(this._pin, frequency);
|
|
62
|
-
return new ToneChain(this._pin, frequency);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
toneFor(frequency: number, duration: number): void {
|
|
66
|
-
tonePlay(this._pin, frequency, duration);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
noTone(): void {
|
|
70
|
-
toneStop(this._pin);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
pwm(duty: number): void {
|
|
74
|
-
pwmWrite(this._pin, duty);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getPwmFrequency(): number {
|
|
78
|
-
return boardResolve("peripherals.pwm.maxFrequency");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getPwmResolution(): number {
|
|
82
|
-
return boardResolve("peripherals.pwm.resolution");
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export class InputPin {
|
|
87
|
-
private _pin: number;
|
|
88
|
-
readonly number: number;
|
|
89
|
-
readonly gpio: number;
|
|
90
|
-
|
|
91
|
-
constructor(pin: number) {
|
|
92
|
-
this._pin = pin;
|
|
93
|
-
this.number = pin;
|
|
94
|
-
this.gpio = pin;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
read(): boolean {
|
|
98
|
-
return gpioRead(this._pin) as unknown as boolean;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
isHigh(): boolean {
|
|
102
|
-
return this.read();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
isLow(): boolean {
|
|
106
|
-
return !this.read();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
readAnalog(): number {
|
|
110
|
-
return adcRead(this._pin);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
readVoltage(): number {
|
|
114
|
-
return adcReadVoltage(this._pin);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
getAnalogResolution(): number {
|
|
118
|
-
return boardResolve("peripherals.adc.0.resolution");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
setAnalogReference(ref: string): void {
|
|
122
|
-
ADC._reference = ref;
|
|
123
|
-
adcSetReference(ref);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
onFalling(handler: () => void): void {
|
|
127
|
-
interruptAttach(this._pin, callback(handler), "FALLING");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
onRising(handler: () => void): void {
|
|
131
|
-
interruptAttach(this._pin, callback(handler), "RISING");
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
onChange(handler: () => void): void {
|
|
135
|
-
interruptAttach(this._pin, callback(handler), "CHANGE");
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
offAll(): void {
|
|
139
|
-
interruptDetach(this._pin);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/** Alias matching the BasePin.offInterrupts() interface name. */
|
|
143
|
-
offInterrupts(): void {
|
|
144
|
-
interruptDetach(this._pin);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Wait for a RISING edge on this input pin.
|
|
149
|
-
* Returns a Promise<void> that resolves when the pin transitions from LOW to HIGH.
|
|
150
|
-
* The platform strategy controls whether this uses interrupts, polling, or a stub.
|
|
151
|
-
*
|
|
152
|
-
* @param timeout Optional timeout in milliseconds. If provided, the promise
|
|
153
|
-
* rejects (or resolves with a false/error) after the timeout expires.
|
|
154
|
-
*/
|
|
155
|
-
waitForRising(timeout?: number): Promise<void> {
|
|
156
|
-
rawCpp(`__cuttlefish_wait_pin_edge(${this._pin}, RISING, ${timeout ?? -1});`);
|
|
157
|
-
return Promise.resolve();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Wait for a FALLING edge on this input pin.
|
|
162
|
-
* Returns a Promise<void> that resolves when the pin transitions from HIGH to LOW.
|
|
163
|
-
*
|
|
164
|
-
* @param timeout Optional timeout in milliseconds. If provided, the promise
|
|
165
|
-
* rejects (or resolves with a false/error) after the timeout expires.
|
|
166
|
-
*/
|
|
167
|
-
waitForFalling(timeout?: number): Promise<void> {
|
|
168
|
-
rawCpp(`__cuttlefish_wait_pin_edge(${this._pin}, FALLING, ${timeout ?? -1});`);
|
|
169
|
-
return Promise.resolve();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export class ToneChain {
|
|
174
|
-
private _pin: number;
|
|
175
|
-
private _lastFreq: number;
|
|
176
|
-
|
|
177
|
-
constructor(pin: number, frequency: number) {
|
|
178
|
-
this._pin = pin;
|
|
179
|
-
this._lastFreq = frequency;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
for(duration: number): void {
|
|
183
|
-
tonePlay(this._pin, this._lastFreq, duration);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Represents a physical hardware pin before it has been configured for a specific mode.
|
|
189
|
-
* Use `.asInput()` or `.asOutput()` to obtain a functional pin instance.
|
|
190
|
-
*
|
|
191
|
-
* Pins can be created two ways:
|
|
192
|
-
* - `new Pin(number)` — legacy, using framework pin number (e.g. Arduino pin 13)
|
|
193
|
-
* - `Pin.fromPort("PB5")` — preferred, using MCU datasheet port name
|
|
194
|
-
*
|
|
195
|
-
* When created via `fromPort()`, the pin carries its canonical port identity.
|
|
196
|
-
* The transpiler resolves the port name to a framework pin number at compile time
|
|
197
|
-
* using the MCU package's pin mapping (e.g. arduino-map.ts).
|
|
198
|
-
*/
|
|
199
|
-
export class Pin {
|
|
200
|
-
/** MCU port name (e.g. "PB5") — empty string for legacy numeric pins */
|
|
201
|
-
private _port: string;
|
|
202
|
-
/** Framework pin number (e.g. 13 for Arduino). -1 for port-based pins. */
|
|
203
|
-
private _pin: number;
|
|
204
|
-
/** Public readonly access to port name */
|
|
205
|
-
readonly port: string;
|
|
206
|
-
readonly number: number;
|
|
207
|
-
readonly gpio: number;
|
|
208
|
-
|
|
209
|
-
/** Legacy constructor — creates a Pin from a framework pin number */
|
|
210
|
-
constructor(pin: number) {
|
|
211
|
-
this._port = '';
|
|
212
|
-
this._pin = pin;
|
|
213
|
-
this.port = '';
|
|
214
|
-
this.number = pin;
|
|
215
|
-
this.gpio = pin;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Create a Pin from its MCU datasheet port name (e.g. "PB5", "PC0").
|
|
220
|
-
* The port name is the canonical identity; framework-specific pin numbers
|
|
221
|
-
* are resolved at transpile time via the MCU package's pin mapping.
|
|
222
|
-
*/
|
|
223
|
-
static fromPort(portName: string): Pin {
|
|
224
|
-
const p = new Pin(-1);
|
|
225
|
-
p._port = portName;
|
|
226
|
-
// Bypass readonly for factory method
|
|
227
|
-
(p as any).port = portName;
|
|
228
|
-
return p;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
asOutput(initial?: number | boolean): OutputPin {
|
|
232
|
-
gpioSetMode(this._pin, "OUTPUT");
|
|
233
|
-
if (initial !== undefined) {
|
|
234
|
-
gpioWrite(this._pin, initial);
|
|
235
|
-
}
|
|
236
|
-
// Returns `this` so the transpiler can suppress the C++ return emission
|
|
237
|
-
// (it resolves `this` to the same instance and tracks the result as an
|
|
238
|
-
// OutputPin via the method name). Returning `new OutputPin(this._pin)`
|
|
239
|
-
// would leak the literal text into generated C++. The cast is required
|
|
240
|
-
// because Pin and OutputPin are structurally distinct classes; the
|
|
241
|
-
// transpiler handles the mode transition semantically.
|
|
242
|
-
return this as unknown as OutputPin;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/** Alias for asOutput() — shorter fluent form. */
|
|
246
|
-
output(initial?: number | boolean): OutputPin {
|
|
247
|
-
gpioSetMode(this._pin, "OUTPUT");
|
|
248
|
-
if (initial !== undefined) {
|
|
249
|
-
gpioWrite(this._pin, initial);
|
|
250
|
-
}
|
|
251
|
-
return this as unknown as OutputPin;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
asInput(): InputPin {
|
|
255
|
-
gpioSetMode(this._pin, "INPUT");
|
|
256
|
-
return this as unknown as InputPin;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
asInputPullUp(): InputPin {
|
|
260
|
-
gpioSetMode(this._pin, "INPUT_PULLUP");
|
|
261
|
-
return this as unknown as InputPin;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
asInputPullDown(): InputPin {
|
|
265
|
-
gpioSetMode(this._pin, "INPUT_PULLDOWN");
|
|
266
|
-
return this as unknown as InputPin;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
inputPullUp(): InputPin {
|
|
270
|
-
gpioSetMode(this._pin, "INPUT_PULLUP");
|
|
271
|
-
return this as unknown as InputPin;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/** Alias for asInputPullDown() — shorter fluent form. */
|
|
275
|
-
inputPullDown(): InputPin {
|
|
276
|
-
gpioSetMode(this._pin, "INPUT_PULLDOWN");
|
|
277
|
-
return this as unknown as InputPin;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
read(): boolean {
|
|
281
|
-
return gpioRead(this._pin) as unknown as boolean;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
isHigh(): boolean {
|
|
285
|
-
return this.read();
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
isLow(): boolean {
|
|
289
|
-
return !this.read();
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
write(value: number | boolean): void {
|
|
293
|
-
gpioWrite(this._pin, value);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
high(): void {
|
|
297
|
-
gpioWrite(this._pin, 1);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
low(): void {
|
|
301
|
-
gpioWrite(this._pin, 0);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
toggle(): void {
|
|
305
|
-
gpioToggle(this._pin);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
pwm(duty: number): void {
|
|
309
|
-
pwmWrite(this._pin, duty);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
tone(frequency: number): ToneChain {
|
|
313
|
-
tonePlay(this._pin, frequency);
|
|
314
|
-
return new ToneChain(this._pin, frequency);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
noTone(): void {
|
|
318
|
-
toneStop(this._pin);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Pin — the board-addressable pin identity (legacy GPIO classes removed)
|
|
3
|
+
//
|
|
4
|
+
// A Pin carries its canonical datasheet port name (Pin.fromPort("PB5")) and/or
|
|
5
|
+
// framework pin number; the transpiler resolves it via the MCU package's pin
|
|
6
|
+
// mapping. It is an ADDRESS, not a configured peripheral — configure pins by
|
|
7
|
+
// constructing the thin peripherals with them:
|
|
8
|
+
//
|
|
9
|
+
// new GPIO(PB5, GPIO.OUTPUT | GPIO.PULL_UP)
|
|
10
|
+
// new PWM(PA5, { periodNs: 20_000_000 })
|
|
11
|
+
// new ADC(A1)
|
|
12
|
+
//
|
|
13
|
+
// The former OutputPin/InputPin/ToneChain classes (and their as*/read/write/
|
|
14
|
+
// pwm methods) were removed with the legacy Arduino surface. Their thin
|
|
15
|
+
// replacements are gpio-pin.ts / pwm-pin.ts / adc-pin.ts.
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export class Pin {
|
|
19
|
+
/** MCU port name (e.g. "PB5") — empty string for legacy numeric pins */
|
|
20
|
+
private _port: string;
|
|
21
|
+
/** Framework pin number (e.g. 13 for Arduino). -1 for port-based pins. */
|
|
22
|
+
private _pin: number;
|
|
23
|
+
/** Public readonly access to port name */
|
|
24
|
+
readonly port: string;
|
|
25
|
+
readonly number: number;
|
|
26
|
+
readonly gpio: number;
|
|
27
|
+
|
|
28
|
+
/** Legacy constructor — creates a Pin from a framework pin number */
|
|
29
|
+
constructor(pin: number) {
|
|
30
|
+
this._port = '';
|
|
31
|
+
this._pin = pin;
|
|
32
|
+
this.port = '';
|
|
33
|
+
this.number = pin;
|
|
34
|
+
this.gpio = pin;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a Pin from its MCU datasheet port name (e.g. "PB5", "PC0").
|
|
39
|
+
* The port name is the canonical identity; framework-specific pin numbers
|
|
40
|
+
* are resolved at transpile time via the MCU package's pin mapping.
|
|
41
|
+
*/
|
|
42
|
+
static fromPort(portName: string): Pin {
|
|
43
|
+
const p = new Pin(-1);
|
|
44
|
+
p._port = portName;
|
|
45
|
+
// Bypass readonly for factory method
|
|
46
|
+
(p as any).port = portName;
|
|
47
|
+
return p;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/http.ts
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Request — the thin HTTP/S client
|
|
3
|
+
//
|
|
4
|
+
// The request is CONSTRUCTION facts: method, URL, and the policy opts
|
|
5
|
+
// (timeout, body, TLS mode) ride the constructor; headers attach with the
|
|
6
|
+
// header() chain; send() lowers the facts into the shim and performs the
|
|
7
|
+
// request; the response is read from this request afterwards (the shim
|
|
8
|
+
// holds the response until the next request).
|
|
9
|
+
//
|
|
10
|
+
// const req = new Request(Request.POST, url, {
|
|
11
|
+
// timeoutMs: 10_000,
|
|
12
|
+
// body: '{"v":1}', json: true,
|
|
13
|
+
// caCert: PEM, // pin a CA (verified TLS)
|
|
14
|
+
// });
|
|
15
|
+
// req.header('X-Custom', 'v');
|
|
16
|
+
// if (req.send()) { console.log(req.status()); }
|
|
17
|
+
//
|
|
18
|
+
// Method tokens: Request.GET / POST / PUT / DELETE / HEAD / PATCH (plain
|
|
19
|
+
// 'GET' strings also accepted). `insecure: true` skips TLS certificate
|
|
20
|
+
// verification (development only). Awaiting send() inside async functions
|
|
21
|
+
// still splits into a background request + done-poll (the async machinery
|
|
22
|
+
// intercepts the send op; the facts were already lowered at send()).
|
|
23
|
+
// ----------------------------------------------------------------------------
|
|
24
|
+
|
|
1
25
|
import {
|
|
2
26
|
httpBegin,
|
|
3
|
-
httpReset,
|
|
4
27
|
httpSetHeader,
|
|
5
28
|
httpSetTimeout,
|
|
6
|
-
httpSetMaxBody,
|
|
7
29
|
httpSetBody,
|
|
8
30
|
httpSetInsecure,
|
|
9
31
|
httpSetCaCert,
|
|
@@ -15,80 +37,71 @@ import {
|
|
|
15
37
|
httpResponseHeader,
|
|
16
38
|
} from './emit.js';
|
|
17
39
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
/** Request construction facts beyond method + URL. */
|
|
41
|
+
export interface RequestOpts {
|
|
42
|
+
/** Response timeout in ms (default 10_000). */
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
/** Request body (raw). */
|
|
45
|
+
body?: string;
|
|
46
|
+
/** The body is JSON — sets the JSON content type. */
|
|
47
|
+
json?: boolean;
|
|
48
|
+
/** Skip TLS certificate verification (development only). */
|
|
49
|
+
insecure?: boolean;
|
|
50
|
+
/** PEM of a trusted CA — enables verified TLS. */
|
|
51
|
+
caCert?: string;
|
|
25
52
|
}
|
|
26
53
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
export class Request {
|
|
55
|
+
static readonly GET = 'GET';
|
|
56
|
+
static readonly POST = 'POST';
|
|
57
|
+
static readonly PUT = 'PUT';
|
|
58
|
+
static readonly DELETE = 'DELETE';
|
|
59
|
+
static readonly HEAD = 'HEAD';
|
|
60
|
+
static readonly PATCH = 'PATCH';
|
|
61
|
+
|
|
62
|
+
private readonly _method: string;
|
|
63
|
+
private readonly _url: string;
|
|
64
|
+
private readonly _timeoutMs: number;
|
|
65
|
+
private readonly _body: string;
|
|
66
|
+
private readonly _json: boolean;
|
|
67
|
+
private readonly _insecure: boolean;
|
|
68
|
+
private readonly _caCert: string;
|
|
69
|
+
|
|
70
|
+
constructor(method: string, url: string, opts: RequestOpts = {}) {
|
|
71
|
+
this._method = method.toUpperCase();
|
|
42
72
|
this._url = url;
|
|
73
|
+
this._timeoutMs = opts.timeoutMs ?? 10_000;
|
|
74
|
+
this._body = opts.body ?? '';
|
|
75
|
+
this._json = opts.json === true;
|
|
76
|
+
this._insecure = opts.insecure === true;
|
|
77
|
+
this._caCert = opts.caCert ?? '';
|
|
43
78
|
}
|
|
44
79
|
|
|
80
|
+
/** Attach a request header. Chainable — one per header. */
|
|
45
81
|
header(name: string, value: string): this {
|
|
46
82
|
httpSetHeader(name, value);
|
|
47
83
|
return this;
|
|
48
84
|
}
|
|
49
85
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
body(data: string): this {
|
|
61
|
-
httpSetBody(data, false);
|
|
62
|
-
return this;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
jsonBody(json: string): this {
|
|
66
|
-
httpSetBody(json, true);
|
|
67
|
-
return this;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** Skip TLS certificate verification (development only). */
|
|
71
|
-
insecure(): this {
|
|
72
|
-
httpSetInsecure();
|
|
73
|
-
return this;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
caCert(pem: string): this {
|
|
77
|
-
httpSetCaCert(pem);
|
|
78
|
-
return this;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Blocking at top level; cooperatively awaitable inside async functions. */
|
|
82
|
-
send(): Promise<boolean> {
|
|
86
|
+
/** Send the request (blocking). The construction facts lower into the
|
|
87
|
+
* shim first (timeout/body/TLS mode), then the request performs.
|
|
88
|
+
* Awaitable inside async functions — the async machinery splits the
|
|
89
|
+
* send into a background request + done-poll. */
|
|
90
|
+
send(): boolean {
|
|
91
|
+
httpSetTimeout(this._timeoutMs);
|
|
92
|
+
httpSetBody(this._body, this._json);
|
|
93
|
+
httpSetInsecure(this._insecure);
|
|
94
|
+
httpSetCaCert(this._caCert);
|
|
83
95
|
httpBegin(this._method, this._url);
|
|
84
|
-
httpSend();
|
|
85
|
-
return Promise.resolve(false);
|
|
96
|
+
return httpSend();
|
|
86
97
|
}
|
|
87
98
|
|
|
99
|
+
/** Response status code (0 before a completed send). */
|
|
88
100
|
status(): number {
|
|
89
101
|
return httpStatus();
|
|
90
102
|
}
|
|
91
103
|
|
|
104
|
+
/** True when the response status is 2xx. */
|
|
92
105
|
ok(): boolean {
|
|
93
106
|
return httpOk();
|
|
94
107
|
}
|
|
@@ -98,47 +111,14 @@ export class HttpRequest {
|
|
|
98
111
|
return httpBody();
|
|
99
112
|
}
|
|
100
113
|
|
|
114
|
+
/** Response Content-Length (0 when absent). */
|
|
101
115
|
contentLength(): number {
|
|
102
116
|
return httpContentLength();
|
|
103
117
|
}
|
|
104
118
|
|
|
119
|
+
/** One response header value ("" when absent; valid until the next
|
|
120
|
+
* request). */
|
|
105
121
|
responseHeader(name: string): string {
|
|
106
122
|
return httpResponseHeader(name);
|
|
107
123
|
}
|
|
108
124
|
}
|
|
109
|
-
|
|
110
|
-
export class HttpClass {
|
|
111
|
-
static readonly __instance_name = "Http";
|
|
112
|
-
|
|
113
|
-
get(url: string): HttpRequest {
|
|
114
|
-
httpReset();
|
|
115
|
-
return new HttpRequest("GET", url);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
post(url: string): HttpRequest {
|
|
119
|
-
httpReset();
|
|
120
|
-
return new HttpRequest("POST", url);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
put(url: string): HttpRequest {
|
|
124
|
-
httpReset();
|
|
125
|
-
return new HttpRequest("PUT", url);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
del(url: string): HttpRequest {
|
|
129
|
-
httpReset();
|
|
130
|
-
return new HttpRequest("DELETE", url);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
head(url: string): HttpRequest {
|
|
134
|
-
httpReset();
|
|
135
|
-
return new HttpRequest("HEAD", url);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
patch(url: string): HttpRequest {
|
|
139
|
-
httpReset();
|
|
140
|
-
return new HttpRequest("PATCH", url);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export const Http = new HttpClass();
|