@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.
Files changed (121) hide show
  1. package/README.md +145 -87
  2. package/dist/adc-pin.d.ts +53 -0
  3. package/dist/adc-pin.js +69 -0
  4. package/dist/async.d.ts +3 -11
  5. package/dist/async.js +3 -15
  6. package/dist/ble.d.ts +42 -78
  7. package/dist/ble.js +79 -98
  8. package/dist/counter.d.ts +16 -0
  9. package/dist/counter.js +32 -0
  10. package/dist/dac-pin.d.ts +13 -0
  11. package/dist/dac-pin.js +21 -0
  12. package/dist/emit.d.ts +123 -196
  13. package/dist/emit.js +146 -208
  14. package/dist/fs.d.ts +12 -31
  15. package/dist/fs.js +30 -40
  16. package/dist/gpio-pin.d.ts +46 -0
  17. package/dist/gpio-pin.js +77 -0
  18. package/dist/gpio.d.ts +0 -103
  19. package/dist/gpio.js +16 -227
  20. package/dist/http.d.ts +38 -39
  21. package/dist/http.js +53 -78
  22. package/dist/i2c-target.d.ts +28 -0
  23. package/dist/i2c-target.js +52 -0
  24. package/dist/i2c.d.ts +5 -43
  25. package/dist/i2c.js +17 -130
  26. package/dist/index.d.ts +30 -42
  27. package/dist/index.js +27 -39
  28. package/dist/math.d.ts +0 -13
  29. package/dist/math.js +9 -13
  30. package/dist/mqtt.d.ts +15 -25
  31. package/dist/mqtt.js +32 -28
  32. package/dist/power.d.ts +9 -17
  33. package/dist/power.js +22 -20
  34. package/dist/preferences.d.ts +17 -25
  35. package/dist/preferences.js +54 -52
  36. package/dist/pulse.d.ts +4 -4
  37. package/dist/pulse.js +6 -2
  38. package/dist/pwm-pin.d.ts +24 -0
  39. package/dist/pwm-pin.js +38 -0
  40. package/dist/random.d.ts +0 -2
  41. package/dist/random.js +14 -20
  42. package/dist/sensor-catalog.generated.d.ts +997 -0
  43. package/dist/sensor-catalog.generated.js +764 -0
  44. package/dist/sensor.d.ts +46 -0
  45. package/dist/sensor.js +52 -0
  46. package/dist/shift-pin.d.ts +2 -0
  47. package/dist/shift-pin.js +13 -0
  48. package/dist/spi-target.d.ts +25 -0
  49. package/dist/spi-target.js +42 -0
  50. package/dist/spi.d.ts +8 -26
  51. package/dist/spi.js +15 -87
  52. package/dist/thread.d.ts +18 -0
  53. package/dist/thread.js +36 -0
  54. package/dist/time.d.ts +23 -0
  55. package/dist/time.js +43 -0
  56. package/dist/timing.d.ts +17 -7
  57. package/dist/timing.js +17 -7
  58. package/dist/types.d.ts +4 -34
  59. package/dist/types.js +5 -47
  60. package/dist/uart-port.d.ts +26 -0
  61. package/dist/uart-port.js +52 -0
  62. package/dist/uart.d.ts +0 -17
  63. package/dist/uart.js +10 -53
  64. package/dist/usb.d.ts +26 -0
  65. package/dist/usb.js +66 -0
  66. package/dist/watchdog.d.ts +12 -0
  67. package/dist/watchdog.js +28 -0
  68. package/dist/wifi.d.ts +88 -64
  69. package/dist/wifi.js +112 -126
  70. package/dist/zephyr-tokens.generated.d.ts +8 -0
  71. package/dist/zephyr-tokens.generated.js +73 -0
  72. package/package.json +7 -8
  73. package/src/adc-pin.ts +89 -0
  74. package/src/async.ts +3 -16
  75. package/src/ble.ts +84 -111
  76. package/src/counter.ts +40 -0
  77. package/src/dac-pin.ts +28 -0
  78. package/src/emit.ts +157 -238
  79. package/src/fs.ts +47 -54
  80. package/src/gpio-pin.ts +91 -0
  81. package/src/gpio.ts +49 -320
  82. package/src/http.ts +75 -95
  83. package/src/i2c-target.ts +63 -0
  84. package/src/i2c.ts +29 -167
  85. package/src/index.ts +32 -46
  86. package/src/math.ts +9 -14
  87. package/src/mqtt.ts +39 -31
  88. package/src/preferences.ts +52 -61
  89. package/src/pwm-pin.ts +54 -0
  90. package/src/random.ts +14 -21
  91. package/src/sensor-catalog.generated.ts +1238 -0
  92. package/src/sensor.ts +80 -0
  93. package/src/shift-pin.ts +16 -0
  94. package/src/spi-target.ts +53 -0
  95. package/src/spi.ts +27 -121
  96. package/src/thread.ts +44 -0
  97. package/src/time.ts +50 -0
  98. package/src/types.ts +14 -89
  99. package/src/uart-port.ts +64 -0
  100. package/src/usb.ts +82 -0
  101. package/src/watchdog.ts +35 -0
  102. package/src/wifi.ts +147 -179
  103. package/src/zephyr-tokens.generated.ts +77 -0
  104. package/src/adc.ts +0 -30
  105. package/src/capacitive.ts +0 -31
  106. package/src/constants.ts +0 -23
  107. package/src/dac.ts +0 -21
  108. package/src/eeprom.ts +0 -26
  109. package/src/interrupts.ts +0 -35
  110. package/src/mdns.ts +0 -50
  111. package/src/ota.ts +0 -44
  112. package/src/power.ts +0 -36
  113. package/src/pulse.ts +0 -63
  114. package/src/rmt.ts +0 -125
  115. package/src/shift.ts +0 -88
  116. package/src/temperature.ts +0 -20
  117. package/src/timer.ts +0 -58
  118. package/src/timing.ts +0 -67
  119. package/src/uart.ts +0 -77
  120. package/src/utils.ts +0 -17
  121. package/src/wdt.ts +0 -17
@@ -0,0 +1,46 @@
1
+ import type { I2CTarget } from './i2c-target.js';
2
+ import type { SPITarget } from './spi-target.js';
3
+ import type { SensorChannelOf, SensorBusOf } from './sensor-catalog.generated.js';
4
+ /** Part ids the catalog knows (the Sensor<P> narrowing keys). */
5
+ type SensorPartId = keyof SensorChannelOf;
6
+ /** The bus-device argument a part accepts, from its generated bus map:
7
+ * SPI-only parts take SPITarget, I2C-only take I2CTarget, dual-bus either. */
8
+ type BusDeviceFor<B extends string> = B extends 'spi' ? SPITarget : B extends 'i2c' ? I2CTarget : I2CTarget | SPITarget;
9
+ export type SensorBusDevice<P extends SensorPartId = SensorPartId> = BusDeviceFor<SensorBusOf[P]>;
10
+ /** Construction options. */
11
+ export interface SensorOptions {
12
+ /** SPI clock in Hz, SPI parts only. Default 1 MHz (safe for every
13
+ * catalog part); raise to the breakout's datasheet maximum. */
14
+ spiHz?: number;
15
+ /** SPI mode (CPOL/CPHA bits), 0-3. Default 0. */
16
+ mode?: 0 | 1 | 2 | 3;
17
+ /** Alert GPIO, for parts whose binding declares alert-gpios. */
18
+ alert?: number;
19
+ }
20
+ export declare class Sensor<P extends SensorPartId = SensorPartId> {
21
+ private readonly _part;
22
+ private readonly _bus;
23
+ private readonly _port;
24
+ private readonly _kind;
25
+ private readonly _spiHz;
26
+ private readonly _mode;
27
+ private readonly _alert;
28
+ /** Construct a sensor handle. `part` is a `SENSOR.<name>` token;
29
+ * `dev` is the bus device (e.g. `I2C1.device(0x44)`) carrying the bus
30
+ * and address. The transpiler resolves the bus instance and address from
31
+ * `dev` — the class fields are the IR carrier, not runtime state.
32
+ * The `P` parameter is editor-only: it narrows `get()` to this part's
33
+ * channels (from the generated SensorChannelOf map); the transpiler
34
+ * re-validates at build time with the driver's full channel list. */
35
+ constructor(part: P, dev: SensorBusDevice<P>, opts?: SensorOptions);
36
+ /** Fetch a fresh sample (sensor_sample_fetch). Reads reflect the last
37
+ * fetch — Zephyr's own fetch/get split, kept verbatim. */
38
+ fetch(): void;
39
+ /** Read one channel from the fetched sample (sensor_channel_get).
40
+ * Returns the value as a double (val1 + val2/1e6). The parameter is
41
+ * narrowed to this part's channels when constructed from a literal
42
+ * SENSOR token — `sht3x.get(` completes AMBIENT_TEMP | HUMIDITY and
43
+ * rejects the rest in the editor. */
44
+ get(chan: SensorChannelOf[P]): number;
45
+ }
46
+ export {};
package/dist/sensor.js ADDED
@@ -0,0 +1,52 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Sensor — generic DT-bound sensor part (Zephyr's uniform sensor API)
3
+ //
4
+ // `new Sensor(SENSOR.sensirion_sht3xd, I2C1.device(0x44))` covers every part
5
+ // in the generated catalog: the constructor's facts (part token + bus +
6
+ // address) become a devicetree child node in the generated overlay, and the
7
+ // methods lower to Zephyr's one-shape sensor API (sensor_sample_fetch /
8
+ // sensor_channel_get). No per-part code exists anywhere — the catalog
9
+ // (sensor-catalog.generated.ts) is data, generated from Zephyr's own binding
10
+ // YAMLs and driver channel tables.
11
+ //
12
+ // The channel names are Zephyr verbiage minus the SENSOR_CHAN_ prefix
13
+ // (CHAN.AMBIENT_TEMP ↔ SENSOR_CHAN_AMBIENT_TEMP), so any Zephyr sample or
14
+ // binding doc greps straight into user code.
15
+ // ---------------------------------------------------------------------------
16
+ import { sensorFetch, sensorGet } from './emit.js';
17
+ import { include } from './include.js';
18
+ export class Sensor {
19
+ /** Construct a sensor handle. `part` is a `SENSOR.<name>` token;
20
+ * `dev` is the bus device (e.g. `I2C1.device(0x44)`) carrying the bus
21
+ * and address. The transpiler resolves the bus instance and address from
22
+ * `dev` — the class fields are the IR carrier, not runtime state.
23
+ * The `P` parameter is editor-only: it narrows `get()` to this part's
24
+ * channels (from the generated SensorChannelOf map); the transpiler
25
+ * re-validates at build time with the driver's full channel list. */
26
+ constructor(part, dev, opts) {
27
+ this._bus = '';
28
+ this._port = 0;
29
+ this._kind = 'i2c';
30
+ this._spiHz = 1000000;
31
+ this._mode = 0;
32
+ this._alert = -1;
33
+ this._part = part;
34
+ void dev;
35
+ void opts;
36
+ }
37
+ /** Fetch a fresh sample (sensor_sample_fetch). Reads reflect the last
38
+ * fetch — Zephyr's own fetch/get split, kept verbatim. */
39
+ fetch() {
40
+ include('<zephyr/drivers/sensor.h>');
41
+ sensorFetch(this._part, this._bus, this._port, this._kind, this._spiHz, this._mode, this._alert);
42
+ }
43
+ /** Read one channel from the fetched sample (sensor_channel_get).
44
+ * Returns the value as a double (val1 + val2/1e6). The parameter is
45
+ * narrowed to this part's channels when constructed from a literal
46
+ * SENSOR token — `sht3x.get(` completes AMBIENT_TEMP | HUMIDITY and
47
+ * rejects the rest in the editor. */
48
+ get(chan) {
49
+ include('<zephyr/drivers/sensor.h>');
50
+ return sensorGet(this._part, this._bus, this._port, this._kind, this._spiHz, this._mode, this._alert, chan);
51
+ }
52
+ }
@@ -0,0 +1,2 @@
1
+ export declare function shiftOut(dataPin: number, clockPin: number, value: number, msbFirst?: boolean): void;
2
+ export declare function shiftIn(dataPin: number, clockPin: number, msbFirst?: boolean): number;
@@ -0,0 +1,13 @@
1
+ // ---------------------------------------------------------------------------
2
+ // shiftOut / shiftIn — the thin bit-bang shift (the legacy shiftOut/shiftIn
3
+ // shape, Zephyr-lowered): clock idles low; each bit sets data then pulses the
4
+ // clock. For real SPI, use SPITarget. Pin arguments accept board pin aliases
5
+ // (resolved to their numbers by the transpiler).
6
+ // ---------------------------------------------------------------------------
7
+ import { gpioShiftOut, gpioShiftIn } from './emit.js';
8
+ export function shiftOut(dataPin, clockPin, value, msbFirst = true) {
9
+ gpioShiftOut(dataPin, clockPin, value, msbFirst);
10
+ }
11
+ export function shiftIn(dataPin, clockPin, msbFirst = true) {
12
+ return gpioShiftIn(dataPin, clockPin, msbFirst);
13
+ }
@@ -0,0 +1,25 @@
1
+ import type { Pin } from './gpio.js';
2
+ export declare class SPITarget {
3
+ private readonly _bus;
4
+ private readonly _cs;
5
+ private readonly _hz;
6
+ private readonly _mode;
7
+ /** Construct a device handle. `bus` is the bus instance (SPI0, …); `cs`
8
+ * is the chip-select pin; `hz` the bus clock (spi-max-frequency, default
9
+ * 1 MHz conservative); `mode` the SPI mode 0–3. */
10
+ constructor(bus: string, cs: number | Pin, opts?: {
11
+ hz?: number;
12
+ mode?: 0 | 1 | 2 | 3;
13
+ });
14
+ /** Full-duplex transfer (spi_transceive_dt): `tx` bytes out while `rx`
15
+ * captures — the buffer you pass is the buffer filled, so declare it and
16
+ * read it directly (rx.length decides the capture length). Omit `rx`
17
+ * for a write-only transfer. */
18
+ transceive(tx: number[] | Uint8Array, rx?: Uint8Array): void;
19
+ /** Write bytes (spi_write_dt) — no capture. */
20
+ write(tx: number[] | Uint8Array): void;
21
+ /** Register read sugar: sends `reg`, returns the one captured byte
22
+ * (spi_transceive_dt against an internal buffer — e.g. a BME280's ID
23
+ * register 0xD0 reads 0x60). */
24
+ readReg(reg: number): number;
25
+ }
@@ -0,0 +1,42 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SPITarget — the thin Zephyr-shaped SPI device
3
+ //
4
+ // A chip-select peer on an SPI bus, addressed the Zephyr way: construction
5
+ // emits a devicetree child node (cs-gpios index + spi-max-frequency + mode
6
+ // bits — the same machinery sensors ride), and the verbs lower to
7
+ // spi_transceive_dt / spi_write_dt against a static spi_dt_spec. Hardware
8
+ // CS, no manual GPIO toggling, no runtime spi_config rebuilding.
9
+ //
10
+ // `bus` is the board's bus instance export (SPI0/SPI1), `cs` the chip-select
11
+ // pin, and the options are the wire facts: `hz` (spi-max-frequency) and
12
+ // `mode` (CPOL/CPHA bits 0–3 → spi-cpol/spi-cpha).
13
+ // ----------------------------------------------------------------------------
14
+ import { spiTransceiveDt, spiWriteDt, spiReadReg } from './emit.js';
15
+ export class SPITarget {
16
+ /** Construct a device handle. `bus` is the bus instance (SPI0, …); `cs`
17
+ * is the chip-select pin; `hz` the bus clock (spi-max-frequency, default
18
+ * 1 MHz conservative); `mode` the SPI mode 0–3. */
19
+ constructor(bus, cs, opts) {
20
+ this._bus = bus;
21
+ this._cs = typeof cs === 'number' ? cs : cs.number;
22
+ this._hz = opts?.hz ?? 1000000;
23
+ this._mode = opts?.mode ?? 0;
24
+ }
25
+ /** Full-duplex transfer (spi_transceive_dt): `tx` bytes out while `rx`
26
+ * captures — the buffer you pass is the buffer filled, so declare it and
27
+ * read it directly (rx.length decides the capture length). Omit `rx`
28
+ * for a write-only transfer. */
29
+ transceive(tx, rx) {
30
+ spiTransceiveDt(this._bus, this._cs, this._hz, this._mode, tx, rx ?? new Uint8Array(0));
31
+ }
32
+ /** Write bytes (spi_write_dt) — no capture. */
33
+ write(tx) {
34
+ spiWriteDt(this._bus, this._cs, this._hz, this._mode, tx);
35
+ }
36
+ /** Register read sugar: sends `reg`, returns the one captured byte
37
+ * (spi_transceive_dt against an internal buffer — e.g. a BME280's ID
38
+ * register 0xD0 reads 0x60). */
39
+ readReg(reg) {
40
+ return spiReadReg(this._bus, this._cs, this._hz, this._mode, reg);
41
+ }
42
+ }
package/dist/spi.d.ts CHANGED
@@ -1,31 +1,13 @@
1
+ import { SPITarget } from './spi-target.js';
1
2
  import type { Pin } from './gpio.js';
2
- import type { SPIMode, SPISettings } from './types.js';
3
- export declare class SPIDevice {
4
- private _bus;
5
- private _cs;
6
- constructor(bus: string, chipSelect: number);
7
- transfer(data: number | Uint8Array): number;
8
- write(data: number | Uint8Array): void;
9
- readRegister(register: number, count: number): Uint8Array;
10
- writeRegister(register: number, value: number): void;
11
- }
12
3
  export declare class SPIBus {
13
- static readonly __includes: string[];
14
4
  private _bus;
15
5
  constructor(bus: string);
16
- device(chipSelect: Pin): SPIDevice;
17
- begin(): this;
18
- end(): void;
19
- take(): this | null;
20
- release(): void;
21
- transfer(value: number | Uint8Array): number;
22
- setFrequency(hz: number): void;
23
- beginTransaction(settings: SPISettings): void;
24
- endTransaction(): void;
25
- setMode(mode: SPIMode): void;
26
- setBitOrder(order: 'lsb' | 'msb'): void;
27
- write(value: number): void;
28
- write16(value: number): void;
6
+ /** The functional device target behind `chipSelect` on this controller —
7
+ * transceive/write/regRead verbs callable directly, and the fact-carrier
8
+ * `new Sensor(...)` accepts. */
9
+ device(chipSelect: Pin, opts?: {
10
+ hz?: number;
11
+ mode?: 0 | 1 | 2 | 3;
12
+ }): SPITarget;
29
13
  }
30
- /** Map TypeCAD SPI instance number to Arduino C++ object name. SPI0→SPI, SPI1→SPI1 */
31
- export declare function spiName(instance: number): string;
package/dist/spi.js CHANGED
@@ -1,93 +1,21 @@
1
- import { spiBegin, spiEnd, spiTransfer, spiBeginTx, spiEndTx, spiCsLow, spiCsHigh, spiSetMode, spiSetBitOrder, spiReadBuffer, rawCpp } from './emit.js';
2
- import { include } from './include.js';
3
- export class SPIDevice {
4
- constructor(bus, chipSelect) {
5
- this._bus = bus;
6
- this._cs = chipSelect;
7
- }
8
- transfer(data) {
9
- include("<SPI.h>");
10
- spiCsLow(this._cs);
11
- rawCpp(`auto __res = ${this._bus}.transfer(${data});`);
12
- spiCsHigh(this._cs);
13
- rawCpp(`return __res;`);
14
- return 0;
15
- }
16
- write(data) {
17
- include("<SPI.h>");
18
- spiCsLow(this._cs);
19
- spiTransfer(this._bus, data);
20
- spiCsHigh(this._cs);
21
- }
22
- readRegister(register, count) {
23
- include("<SPI.h>");
24
- spiCsLow(this._cs);
25
- spiTransfer(this._bus, register);
26
- // Clock `count` dummy bytes and drain them into the caller's buffer
27
- // (declared by the Uint8Array return marker as `uint8_t data[count]`).
28
- // Using the semantic primitive — NOT rawCpp — keeps the buffer in user
29
- // scope so it survives the return (no decayed pointer) and `data.length`
30
- // / `data[i]` work, mirroring I2CDevice.readBytes.
31
- spiReadBuffer(this._bus, count, new Uint8Array(count));
32
- spiCsHigh(this._cs);
33
- return new Uint8Array(count);
34
- }
35
- writeRegister(register, value) {
36
- include("<SPI.h>");
37
- spiCsLow(this._cs);
38
- spiTransfer(this._bus, register);
39
- spiTransfer(this._bus, value);
40
- spiCsHigh(this._cs);
41
- }
42
- }
1
+ // ---------------------------------------------------------------------------
2
+ // SPI controller selector (legacy SPI API removed)
3
+ //
4
+ // The bus singletons (SPI0/SPI1…) are CONTROLLER SELECTORS; device(cs, opts?)
5
+ // hands back the FUNCTIONAL SPITarget directly — transceive/write/regRead
6
+ // verbs callable with no further construction. Equivalent to
7
+ // `new SPITarget(this, cs, opts)`. The standalone SPIDevice fact-carrier was
8
+ // absorbed by SPITarget.
9
+ // ----------------------------------------------------------------------------
10
+ import { SPITarget } from './spi-target.js';
43
11
  export class SPIBus {
44
12
  constructor(bus) {
45
13
  this._bus = bus;
46
14
  }
47
- device(chipSelect) {
48
- return new SPIDevice(this._bus, chipSelect.number);
49
- }
50
- begin() {
51
- include("<SPI.h>");
52
- spiBegin(this._bus);
53
- return this;
54
- }
55
- end() {
56
- spiEnd(this._bus);
57
- }
58
- take() {
59
- return this;
15
+ /** The functional device target behind `chipSelect` on this controller —
16
+ * transceive/write/regRead verbs callable directly, and the fact-carrier
17
+ * `new Sensor(...)` accepts. */
18
+ device(chipSelect, opts) {
19
+ return new SPITarget(this._bus, chipSelect, opts);
60
20
  }
61
- release() {
62
- // No-op for standard Arduino.
63
- }
64
- transfer(value) {
65
- return spiTransfer(this._bus, value);
66
- }
67
- setFrequency(hz) {
68
- spiBeginTx(this._bus, `SPISettings(${hz}, MSBFIRST, SPI_MODE0)`);
69
- }
70
- beginTransaction(settings) {
71
- spiBeginTx(this._bus, settings);
72
- }
73
- endTransaction() {
74
- spiEndTx(this._bus);
75
- }
76
- setMode(mode) {
77
- spiSetMode(this._bus, mode);
78
- }
79
- setBitOrder(order) {
80
- spiSetBitOrder(this._bus, order);
81
- }
82
- write(value) {
83
- spiTransfer(this._bus, value);
84
- }
85
- write16(value) {
86
- rawCpp(`${this._bus}.transfer16(${value});`);
87
- }
88
- }
89
- SPIBus.__includes = ["<SPI.h>"];
90
- /** Map TypeCAD SPI instance number to Arduino C++ object name. SPI0→SPI, SPI1→SPI1 */
91
- export function spiName(instance) {
92
- return instance === 0 ? "SPI" : `SPI${instance}`;
93
21
  }
@@ -0,0 +1,18 @@
1
+ export declare class Thread {
2
+ private readonly _index;
3
+ private readonly _stackBytes;
4
+ private readonly _priority;
5
+ /** Construct a thread handle. `stackKb` defaults to 2 (generous for
6
+ * generated code); `priority` defaults to 5 — preemptive, below main. */
7
+ constructor(index: number, opts?: {
8
+ stackKb?: number;
9
+ priority?: number;
10
+ });
11
+ /** Create the thread and schedule it immediately (k_thread_create with
12
+ * K_NO_WAIT). The entry function runs concurrently with main from here. */
13
+ start(fn: () => void): void;
14
+ /** Block until the thread exits (k_thread_join with K_FOREVER). Requires
15
+ * a prior start() on the same index — an unstarted slot is a build
16
+ * error naming the slot's symbol. */
17
+ join(): void;
18
+ }
package/dist/thread.js ADDED
@@ -0,0 +1,36 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Thread — the thin Zephyr-shaped thread
3
+ //
4
+ // k_thread_create / k_thread_join with Zephyr's own model: construction
5
+ // carries the thread's facts (stack size, priority); start(fn) creates and
6
+ // schedules it (K_NO_WAIT — running immediately); join() blocks until it
7
+ // exits (K_FOREVER). The entry function is a no-argument closure, trampolined
8
+ // through Zephyr's (void*, void*, void*) entry signature — the same
9
+ // callback machinery interrupts use.
10
+ //
11
+ // The `index` is the thread's identity (0, 1, 2, …) — the slot its stack and
12
+ // k_thread state occupy, like Counter's instance. Priorities: Zephyr's scale
13
+ // — 5 (the default) is preemptive, below main; negative would be cooperative.
14
+ // ----------------------------------------------------------------------------
15
+ import { threadStart, threadJoin } from './emit.js';
16
+ import { callback } from './callback.js';
17
+ export class Thread {
18
+ /** Construct a thread handle. `stackKb` defaults to 2 (generous for
19
+ * generated code); `priority` defaults to 5 — preemptive, below main. */
20
+ constructor(index, opts) {
21
+ this._index = index;
22
+ this._stackBytes = (opts?.stackKb ?? 2) * 1024;
23
+ this._priority = opts?.priority ?? 5;
24
+ }
25
+ /** Create the thread and schedule it immediately (k_thread_create with
26
+ * K_NO_WAIT). The entry function runs concurrently with main from here. */
27
+ start(fn) {
28
+ threadStart(this._index, this._stackBytes, this._priority, callback(fn));
29
+ }
30
+ /** Block until the thread exits (k_thread_join with K_FOREVER). Requires
31
+ * a prior start() on the same index — an unstarted slot is a build
32
+ * error naming the slot's symbol. */
33
+ join() {
34
+ threadJoin(this._index);
35
+ }
36
+ }
package/dist/time.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ export declare class TimeClass {
2
+ static readonly __instance_name = "Time";
3
+ /** Yielding sleep in milliseconds (k_msleep). On the generated
4
+ * single-threaded main this blocks the caller — the same semantics
5
+ * delay() had, JS-spelled. Inside an async function, `await`-ed it
6
+ * becomes cooperative: the async state machine arms a deadline and
7
+ * yields (other tasks and timers run) until it passes — the same
8
+ * machinery `await delay()` rides. */
9
+ sleep(ms: number): Promise<void>;
10
+ /** Milliseconds since boot as a double (k_uptime_get) — Date.now()-shaped:
11
+ * milliseconds, monotonic, no uint32 wrap. */
12
+ now(): number;
13
+ /** Microseconds since boot as a double — uptime-derived
14
+ * (k_uptime_get() * 1000) on every board: the cycle-counter form reads a
15
+ * constant on SoCs without a free-running 64-bit counter, so the one
16
+ * uniform, monotonic expression wins. Resolution is the uptime tick
17
+ * (millisecond); for sub-ms determinism use Counter (hardware timer). */
18
+ nowUs(): number;
19
+ /** Spin-wait the given microseconds (k_busy_wait) — no yield; for sub-ms
20
+ * protocol timing where a schedule point would break the waveform. */
21
+ busyWaitUs(us: number): void;
22
+ }
23
+ export declare const Time: TimeClass;
package/dist/time.js ADDED
@@ -0,0 +1,43 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Time — the TS-flavored timing surface
3
+ //
4
+ // The Arduino-named forms (delay/millis/micros/delayMicroseconds, module
5
+ // functions and the Timing class) are deprecated for new code but keep
6
+ // lowering — framework-arduino is frozen on them. Time is the replacement:
7
+ // plain-number milliseconds like the rest of the JS ecosystem (Date.now() is
8
+ // ms), microseconds explicit in the name, and the honest Zephyr verbs —
9
+ // k_msleep (yielding sleep), k_uptime_get (ms clock), k_busy_wait (spin).
10
+ // ---------------------------------------------------------------------------
11
+ import { timeSleep, timeNow, timeNowUs, timeBusyWaitUs } from './emit.js';
12
+ export class TimeClass {
13
+ /** Yielding sleep in milliseconds (k_msleep). On the generated
14
+ * single-threaded main this blocks the caller — the same semantics
15
+ * delay() had, JS-spelled. Inside an async function, `await`-ed it
16
+ * becomes cooperative: the async state machine arms a deadline and
17
+ * yields (other tasks and timers run) until it passes — the same
18
+ * machinery `await delay()` rides. */
19
+ sleep(ms) {
20
+ timeSleep(ms);
21
+ return Promise.resolve();
22
+ }
23
+ /** Milliseconds since boot as a double (k_uptime_get) — Date.now()-shaped:
24
+ * milliseconds, monotonic, no uint32 wrap. */
25
+ now() {
26
+ return timeNow();
27
+ }
28
+ /** Microseconds since boot as a double — uptime-derived
29
+ * (k_uptime_get() * 1000) on every board: the cycle-counter form reads a
30
+ * constant on SoCs without a free-running 64-bit counter, so the one
31
+ * uniform, monotonic expression wins. Resolution is the uptime tick
32
+ * (millisecond); for sub-ms determinism use Counter (hardware timer). */
33
+ nowUs() {
34
+ return timeNowUs();
35
+ }
36
+ /** Spin-wait the given microseconds (k_busy_wait) — no yield; for sub-ms
37
+ * protocol timing where a schedule point would break the waveform. */
38
+ busyWaitUs(us) {
39
+ timeBusyWaitUs(us);
40
+ }
41
+ }
42
+ TimeClass.__instance_name = 'Time';
43
+ export const Time = new TimeClass();
package/dist/timing.d.ts CHANGED
@@ -1,8 +1,20 @@
1
+ /**
2
+ * The Arduino-named timing surface. Deprecated for new code — use `Time`
3
+ * (hal/time.ts): `Time.sleep`, `Time.now`, `Time.nowUs`, `Time.busyWaitUs`.
4
+ * Kept lowering: framework-arduino is frozen on this vocabulary, so this
5
+ * class is permanent, not scheduled for removal.
6
+ *
7
+ * @deprecated Use `Time` from '@typecad/hal'.
8
+ */
1
9
  export declare class TimingClass {
2
10
  static readonly __instance_name = "Timing";
11
+ /** @deprecated Use `Time.sleep(ms)`. */
3
12
  millis(): number;
13
+ /** @deprecated Use `Time.nowUs()`. */
4
14
  micros(): number;
15
+ /** @deprecated Use `Time.sleep(ms)`. */
5
16
  delay(ms: number): void;
17
+ /** @deprecated Use `Time.busyWaitUs(us)`. */
6
18
  delayMicroseconds(us: number): void;
7
19
  freeHeap(): number;
8
20
  setInterval(handler: () => void, timeout: number): number;
@@ -11,19 +23,17 @@ export declare class TimingClass {
11
23
  clearTimeout(id: number): void;
12
24
  }
13
25
  export declare const Timing: TimingClass;
26
+ /** @deprecated Use `Time.sleep(ms)`. */
14
27
  export declare function delay(ms: number): void;
28
+ /** @deprecated Use `Time.now()`. */
15
29
  export declare function millis(): number;
30
+ /** @deprecated Use `Time.nowUs()`. */
16
31
  export declare function micros(): number;
32
+ /** @deprecated Use `Time.busyWaitUs(us)`. */
17
33
  export declare function delayMicroseconds(us: number): void;
34
+ /** @deprecated Use `Time.freeHeap()`. */
18
35
  export declare function freeHeap(): number;
19
36
  export declare function setInterval(handler: () => void, timeout: number): number;
20
37
  export declare function setTimeout(handler: () => void, timeout: number): number;
21
38
  export declare function clearInterval(id: number): void;
22
39
  export declare function clearTimeout(id: number): void;
23
- /** Re-map a number from one range to another. Passes through to the Arduino
24
- * core `map()` macro — the transpiler lowers this to a bare `map(...)` call,
25
- * so the target framework must provide the implementation (Arduino.h does). */
26
- export declare function map(value: number, fromLow: number, fromHigh: number, toLow: number, toHigh: number): number;
27
- /** Constrain a number to a range. Passes through to the Arduino core
28
- * `constrain()` macro — see note on `map()` above. */
29
- export declare function constrain(value: number, low: number, high: number): number;
package/dist/timing.js CHANGED
@@ -1,9 +1,21 @@
1
1
  import { rawCpp, getMillis, getMicros, getFreeHeap, delayMs, delayMicro } from './emit.js';
2
2
  import { callback } from './callback.js';
3
+ /**
4
+ * The Arduino-named timing surface. Deprecated for new code — use `Time`
5
+ * (hal/time.ts): `Time.sleep`, `Time.now`, `Time.nowUs`, `Time.busyWaitUs`.
6
+ * Kept lowering: framework-arduino is frozen on this vocabulary, so this
7
+ * class is permanent, not scheduled for removal.
8
+ *
9
+ * @deprecated Use `Time` from '@typecad/hal'.
10
+ */
3
11
  export class TimingClass {
12
+ /** @deprecated Use `Time.sleep(ms)`. */
4
13
  millis() { return getMillis(); }
14
+ /** @deprecated Use `Time.nowUs()`. */
5
15
  micros() { return getMicros(); }
16
+ /** @deprecated Use `Time.sleep(ms)`. */
6
17
  delay(ms) { delayMs(ms); }
18
+ /** @deprecated Use `Time.busyWaitUs(us)`. */
7
19
  delayMicroseconds(us) { delayMicro(us); }
8
20
  freeHeap() {
9
21
  return getFreeHeap();
@@ -25,10 +37,15 @@ export class TimingClass {
25
37
  }
26
38
  TimingClass.__instance_name = "Timing";
27
39
  export const Timing = new TimingClass();
40
+ /** @deprecated Use `Time.sleep(ms)`. */
28
41
  export function delay(ms) { delayMs(ms); }
42
+ /** @deprecated Use `Time.now()`. */
29
43
  export function millis() { return getMillis(); }
44
+ /** @deprecated Use `Time.nowUs()`. */
30
45
  export function micros() { return getMicros(); }
46
+ /** @deprecated Use `Time.busyWaitUs(us)`. */
31
47
  export function delayMicroseconds(us) { delayMicro(us); }
48
+ /** @deprecated Use `Time.freeHeap()`. */
32
49
  export function freeHeap() { return Timing.freeHeap(); }
33
50
  export function setInterval(handler, timeout) {
34
51
  rawCpp(`return __tc_setInterval(${callback(handler)}, ${timeout});`);
@@ -44,10 +61,3 @@ export function clearInterval(id) {
44
61
  export function clearTimeout(id) {
45
62
  rawCpp(`__tc_clearTimeout(${id});`);
46
63
  }
47
- /** Re-map a number from one range to another. Passes through to the Arduino
48
- * core `map()` macro — the transpiler lowers this to a bare `map(...)` call,
49
- * so the target framework must provide the implementation (Arduino.h does). */
50
- export function map(value, fromLow, fromHigh, toLow, toHigh) { return 0; }
51
- /** Constrain a number to a range. Passes through to the Arduino core
52
- * `constrain()` macro — see note on `map()` above. */
53
- export function constrain(value, low, high) { return 0; }
package/dist/types.d.ts CHANGED
@@ -2,6 +2,10 @@
2
2
  export type DigitalValue = boolean;
3
3
  /** An analog value is a plain number (resolution-dependent). */
4
4
  export type AnalogValue = number;
5
+ /** A value a serial port (UART / USB console) can write: text, a number, or
6
+ * a boolean. Numbers format as decimal (integer + trimmed fractional);
7
+ * booleans print as 1/0. */
8
+ export type SerialValue = string | number | boolean;
5
9
  export declare enum PinMode {
6
10
  INPUT = "INPUT",
7
11
  OUTPUT = "OUTPUT",
@@ -10,39 +14,5 @@ export declare enum PinMode {
10
14
  OUTPUT_OPEN_DRAIN = "OUTPUT_OPEN_DRAIN",
11
15
  ANALOG = "ANALOG"
12
16
  }
13
- export declare enum InterruptMode {
14
- RISING = "RISING",
15
- FALLING = "FALLING",
16
- CHANGE = "CHANGE",
17
- LOW = "LOW",
18
- HIGH = "HIGH"
19
- }
20
17
  export type InterruptHandler = () => void;
21
- export interface PinGroupMember {
22
- readonly number: number;
23
- readonly gpio: number;
24
- write(value: DigitalValue): void;
25
- high(): void;
26
- low(): void;
27
- toggle(): void;
28
- read(): DigitalValue;
29
- isHigh(): boolean;
30
- isLow(): boolean;
31
- }
32
- export interface IPinGroup<T extends PinGroupMember = PinGroupMember> {
33
- readonly name: string;
34
- readonly pins: ReadonlyArray<T>;
35
- writePattern(pattern: number): void;
36
- readPattern(): number;
37
- fill(value: DigitalValue): void;
38
- }
39
- export declare function createPinGroup<T extends PinGroupMember>(pins: T[]): IPinGroup<T>;
40
18
  export type ArchitectureIdentifier = 'avr' | 'esp32' | 'esp32s2' | 'esp32s3' | 'esp32c3' | 'esp32c6' | 'rp2040' | 'rp2350' | 'samd' | 'stm32' | 'nrf52' | (string & {});
41
- export type I2CAddress = number;
42
- export type SPIBitOrder = 'msb' | 'lsb';
43
- export type SPIMode = 0 | 1 | 2 | 3;
44
- export interface SPISettings {
45
- frequency: number;
46
- mode: SPIMode;
47
- bitOrder: SPIBitOrder;
48
- }