@typecad/hal 0.1.0-alpha.1

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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/adc.d.ts +13 -0
  4. package/dist/adc.js +22 -0
  5. package/dist/async.d.ts +30 -0
  6. package/dist/async.js +56 -0
  7. package/dist/board.d.ts +3 -0
  8. package/dist/board.js +5 -0
  9. package/dist/callback.d.ts +4 -0
  10. package/dist/callback.js +6 -0
  11. package/dist/constants.d.ts +21 -0
  12. package/dist/constants.js +23 -0
  13. package/dist/dac.d.ts +12 -0
  14. package/dist/dac.js +17 -0
  15. package/dist/eeprom.d.ts +16 -0
  16. package/dist/eeprom.js +21 -0
  17. package/dist/emit.d.ts +121 -0
  18. package/dist/emit.js +177 -0
  19. package/dist/fs.d.ts +13 -0
  20. package/dist/fs.js +39 -0
  21. package/dist/gpio.d.ts +108 -0
  22. package/dist/gpio.js +230 -0
  23. package/dist/i2c.d.ts +40 -0
  24. package/dist/i2c.js +126 -0
  25. package/dist/include.d.ts +5 -0
  26. package/dist/include.js +5 -0
  27. package/dist/index.d.ts +37 -0
  28. package/dist/index.js +30 -0
  29. package/dist/interrupts.d.ts +17 -0
  30. package/dist/interrupts.js +25 -0
  31. package/dist/math.d.ts +22 -0
  32. package/dist/math.js +28 -0
  33. package/dist/power.d.ts +14 -0
  34. package/dist/power.js +21 -0
  35. package/dist/preferences.d.ts +18 -0
  36. package/dist/preferences.js +55 -0
  37. package/dist/pulse.d.ts +24 -0
  38. package/dist/pulse.js +53 -0
  39. package/dist/random.d.ts +12 -0
  40. package/dist/random.js +26 -0
  41. package/dist/register.d.ts +11 -0
  42. package/dist/register.js +21 -0
  43. package/dist/shift.d.ts +31 -0
  44. package/dist/shift.js +71 -0
  45. package/dist/spi.d.ts +31 -0
  46. package/dist/spi.js +90 -0
  47. package/dist/timer.d.ts +35 -0
  48. package/dist/timer.js +50 -0
  49. package/dist/timing.d.ts +29 -0
  50. package/dist/timing.js +53 -0
  51. package/dist/types.d.ts +48 -0
  52. package/dist/types.js +67 -0
  53. package/dist/uart.d.ts +21 -0
  54. package/dist/uart.js +58 -0
  55. package/dist/utils.d.ts +10 -0
  56. package/dist/utils.js +14 -0
  57. package/dist/wdt.d.ts +7 -0
  58. package/dist/wdt.js +14 -0
  59. package/package.json +64 -0
  60. package/src/adc.ts +30 -0
  61. package/src/async.ts +63 -0
  62. package/src/board.ts +5 -0
  63. package/src/callback.ts +6 -0
  64. package/src/constants.ts +23 -0
  65. package/src/dac.ts +21 -0
  66. package/src/eeprom.ts +26 -0
  67. package/src/emit.ts +210 -0
  68. package/src/fs.ts +46 -0
  69. package/src/gpio.ts +298 -0
  70. package/src/i2c.ts +155 -0
  71. package/src/include.ts +5 -0
  72. package/src/index.ts +48 -0
  73. package/src/interrupts.ts +35 -0
  74. package/src/math.ts +32 -0
  75. package/src/power.ts +26 -0
  76. package/src/preferences.ts +58 -0
  77. package/src/pulse.ts +63 -0
  78. package/src/random.ts +31 -0
  79. package/src/register.ts +35 -0
  80. package/src/shift.ts +88 -0
  81. package/src/spi.ts +118 -0
  82. package/src/timer.ts +59 -0
  83. package/src/timing.ts +67 -0
  84. package/src/types.ts +144 -0
  85. package/src/uart.ts +77 -0
  86. package/src/utils.ts +17 -0
  87. package/src/wdt.ts +17 -0
package/src/gpio.ts ADDED
@@ -0,0 +1,298 @@
1
+ import { gpioWrite, gpioRead, gpioToggle, gpioSetMode, tonePlay, toneStop, adcRead, adcReadVoltage, adcSetReference, interruptAttach, interruptDetach, pwmWrite, rawCpp, boardResolve } from './emit.js';
2
+ import { callback } from './callback.js';
3
+ import { ADC } from './adc.js';
4
+
5
+ export class OutputPin {
6
+ private _pin: number;
7
+ readonly number: number;
8
+ readonly gpio: number;
9
+
10
+ constructor(pin: number) {
11
+ this._pin = pin;
12
+ this.number = pin;
13
+ this.gpio = pin;
14
+ }
15
+
16
+ high(): void {
17
+ gpioWrite(this._pin, 1);
18
+ }
19
+
20
+ low(): void {
21
+ gpioWrite(this._pin, 0);
22
+ }
23
+
24
+ toggle(): void {
25
+ gpioToggle(this._pin);
26
+ }
27
+
28
+ write(value: number | boolean): void {
29
+ gpioWrite(this._pin, value);
30
+ }
31
+
32
+ pulse(durationMs: number): void {
33
+ gpioWrite(this._pin, 1);
34
+ rawCpp(`delay(${durationMs});`);
35
+ gpioWrite(this._pin, 0);
36
+ }
37
+
38
+ tone(frequency: number): ToneChain {
39
+ tonePlay(this._pin, frequency);
40
+ return new ToneChain(this._pin, frequency);
41
+ }
42
+
43
+ toneFor(frequency: number, duration: number): void {
44
+ tonePlay(this._pin, frequency, duration);
45
+ }
46
+
47
+ noTone(): void {
48
+ toneStop(this._pin);
49
+ }
50
+
51
+ pwm(duty: number): void {
52
+ pwmWrite(this._pin, duty);
53
+ }
54
+
55
+ getPwmFrequency(): number {
56
+ return boardResolve("peripherals.pwm.maxFrequency");
57
+ }
58
+
59
+ getPwmResolution(): number {
60
+ return boardResolve("peripherals.pwm.resolution");
61
+ }
62
+ }
63
+
64
+ export class InputPin {
65
+ private _pin: number;
66
+ readonly number: number;
67
+ readonly gpio: number;
68
+
69
+ constructor(pin: number) {
70
+ this._pin = pin;
71
+ this.number = pin;
72
+ this.gpio = pin;
73
+ }
74
+
75
+ read(): boolean {
76
+ return gpioRead(this._pin) as unknown as boolean;
77
+ }
78
+
79
+ isHigh(): boolean {
80
+ return this.read();
81
+ }
82
+
83
+ isLow(): boolean {
84
+ return !this.read();
85
+ }
86
+
87
+ readAnalog(): number {
88
+ return adcRead(this._pin);
89
+ }
90
+
91
+ readVoltage(): number {
92
+ return adcReadVoltage(this._pin);
93
+ }
94
+
95
+ getAnalogResolution(): number {
96
+ return boardResolve("peripherals.adc.0.resolution");
97
+ }
98
+
99
+ setAnalogReference(ref: string): void {
100
+ ADC._reference = ref;
101
+ adcSetReference(ref);
102
+ }
103
+
104
+ onFalling(handler: () => void): void {
105
+ interruptAttach(this._pin, callback(handler), "FALLING");
106
+ }
107
+
108
+ onRising(handler: () => void): void {
109
+ interruptAttach(this._pin, callback(handler), "RISING");
110
+ }
111
+
112
+ onChange(handler: () => void): void {
113
+ interruptAttach(this._pin, callback(handler), "CHANGE");
114
+ }
115
+
116
+ offAll(): void {
117
+ interruptDetach(this._pin);
118
+ }
119
+
120
+ /** Alias matching the BasePin.offInterrupts() interface name. */
121
+ offInterrupts(): void {
122
+ interruptDetach(this._pin);
123
+ }
124
+
125
+ /**
126
+ * Wait for a RISING edge on this input pin.
127
+ * Returns a Promise<void> that resolves when the pin transitions from LOW to HIGH.
128
+ * The platform strategy controls whether this uses interrupts, polling, or a stub.
129
+ *
130
+ * @param timeout Optional timeout in milliseconds. If provided, the promise
131
+ * rejects (or resolves with a false/error) after the timeout expires.
132
+ */
133
+ waitForRising(timeout?: number): Promise<void> {
134
+ rawCpp(`__cuttlefish_wait_pin_edge(${this._pin}, RISING, ${timeout ?? -1});`);
135
+ return Promise.resolve();
136
+ }
137
+
138
+ /**
139
+ * Wait for a FALLING edge on this input pin.
140
+ * Returns a Promise<void> that resolves when the pin transitions from HIGH to LOW.
141
+ *
142
+ * @param timeout Optional timeout in milliseconds. If provided, the promise
143
+ * rejects (or resolves with a false/error) after the timeout expires.
144
+ */
145
+ waitForFalling(timeout?: number): Promise<void> {
146
+ rawCpp(`__cuttlefish_wait_pin_edge(${this._pin}, FALLING, ${timeout ?? -1});`);
147
+ return Promise.resolve();
148
+ }
149
+ }
150
+
151
+ export class ToneChain {
152
+ private _pin: number;
153
+ private _lastFreq: number;
154
+
155
+ constructor(pin: number, frequency: number) {
156
+ this._pin = pin;
157
+ this._lastFreq = frequency;
158
+ }
159
+
160
+ for(duration: number): void {
161
+ tonePlay(this._pin, this._lastFreq, duration);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Represents a physical hardware pin before it has been configured for a specific mode.
167
+ * Use `.asInput()` or `.asOutput()` to obtain a functional pin instance.
168
+ *
169
+ * Pins can be created two ways:
170
+ * - `new Pin(number)` — legacy, using framework pin number (e.g. Arduino pin 13)
171
+ * - `Pin.fromPort("PB5")` — preferred, using MCU datasheet port name
172
+ *
173
+ * When created via `fromPort()`, the pin carries its canonical port identity.
174
+ * The transpiler resolves the port name to a framework pin number at compile time
175
+ * using the MCU package's pin mapping (e.g. arduino-map.ts).
176
+ */
177
+ export class Pin {
178
+ /** MCU port name (e.g. "PB5") — empty string for legacy numeric pins */
179
+ private _port: string;
180
+ /** Framework pin number (e.g. 13 for Arduino). -1 for port-based pins. */
181
+ private _pin: number;
182
+ /** Public readonly access to port name */
183
+ readonly port: string;
184
+ readonly number: number;
185
+ readonly gpio: number;
186
+
187
+ /** Legacy constructor — creates a Pin from a framework pin number */
188
+ constructor(pin: number) {
189
+ this._port = '';
190
+ this._pin = pin;
191
+ this.port = '';
192
+ this.number = pin;
193
+ this.gpio = pin;
194
+ }
195
+
196
+ /**
197
+ * Create a Pin from its MCU datasheet port name (e.g. "PB5", "PC0").
198
+ * The port name is the canonical identity; framework-specific pin numbers
199
+ * are resolved at transpile time via the MCU package's pin mapping.
200
+ */
201
+ static fromPort(portName: string): Pin {
202
+ const p = new Pin(-1);
203
+ p._port = portName;
204
+ // Bypass readonly for factory method
205
+ (p as any).port = portName;
206
+ return p;
207
+ }
208
+
209
+ asOutput(initial?: number | boolean): OutputPin {
210
+ gpioSetMode(this._pin, "OUTPUT");
211
+ if (initial !== undefined) {
212
+ gpioWrite(this._pin, initial);
213
+ }
214
+ // Returns `this` so the transpiler can suppress the C++ return emission
215
+ // (it resolves `this` to the same instance and tracks the result as an
216
+ // OutputPin via the method name). Returning `new OutputPin(this._pin)`
217
+ // would leak the literal text into generated C++. The cast is required
218
+ // because Pin and OutputPin are structurally distinct classes; the
219
+ // transpiler handles the mode transition semantically.
220
+ return this as unknown as OutputPin;
221
+ }
222
+
223
+ /** Alias for asOutput() — shorter fluent form. */
224
+ output(initial?: number | boolean): OutputPin {
225
+ gpioSetMode(this._pin, "OUTPUT");
226
+ if (initial !== undefined) {
227
+ gpioWrite(this._pin, initial);
228
+ }
229
+ return this as unknown as OutputPin;
230
+ }
231
+
232
+ asInput(): InputPin {
233
+ gpioSetMode(this._pin, "INPUT");
234
+ return this as unknown as InputPin;
235
+ }
236
+
237
+ asInputPullUp(): InputPin {
238
+ gpioSetMode(this._pin, "INPUT_PULLUP");
239
+ return this as unknown as InputPin;
240
+ }
241
+
242
+ asInputPullDown(): InputPin {
243
+ gpioSetMode(this._pin, "INPUT_PULLDOWN");
244
+ return this as unknown as InputPin;
245
+ }
246
+
247
+ inputPullUp(): InputPin {
248
+ gpioSetMode(this._pin, "INPUT_PULLUP");
249
+ return this as unknown as InputPin;
250
+ }
251
+
252
+ /** Alias for asInputPullDown() — shorter fluent form. */
253
+ inputPullDown(): InputPin {
254
+ gpioSetMode(this._pin, "INPUT_PULLDOWN");
255
+ return this as unknown as InputPin;
256
+ }
257
+
258
+ read(): boolean {
259
+ return gpioRead(this._pin) as unknown as boolean;
260
+ }
261
+
262
+ isHigh(): boolean {
263
+ return this.read();
264
+ }
265
+
266
+ isLow(): boolean {
267
+ return !this.read();
268
+ }
269
+
270
+ write(value: number | boolean): void {
271
+ gpioWrite(this._pin, value);
272
+ }
273
+
274
+ high(): void {
275
+ gpioWrite(this._pin, 1);
276
+ }
277
+
278
+ low(): void {
279
+ gpioWrite(this._pin, 0);
280
+ }
281
+
282
+ toggle(): void {
283
+ gpioToggle(this._pin);
284
+ }
285
+
286
+ pwm(duty: number): void {
287
+ pwmWrite(this._pin, duty);
288
+ }
289
+
290
+ tone(frequency: number): ToneChain {
291
+ tonePlay(this._pin, frequency);
292
+ return new ToneChain(this._pin, frequency);
293
+ }
294
+
295
+ noTone(): void {
296
+ toneStop(this._pin);
297
+ }
298
+ }
package/src/i2c.ts ADDED
@@ -0,0 +1,155 @@
1
+ import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, rawCpp } from './emit.js';
2
+ import { include } from './include.js';
3
+
4
+ export class I2CDevice {
5
+ private _bus: string;
6
+ private _address: number;
7
+
8
+ constructor(bus: string, address: number) {
9
+ this._bus = bus;
10
+ this._address = address;
11
+ }
12
+
13
+ writeByte(register: number, value: number): void {
14
+ include("<Wire.h>");
15
+ i2cBeginTx(this._bus, this._address);
16
+ i2cWrite(this._bus, register);
17
+ i2cWrite(this._bus, value);
18
+ i2cEndTx(this._bus, true);
19
+ }
20
+
21
+ readByte(register: number): number {
22
+ include("<Wire.h>");
23
+ i2cBeginTx(this._bus, this._address);
24
+ i2cWrite(this._bus, register);
25
+ i2cEndTx(this._bus, false);
26
+ i2cRequestFrom(this._bus, this._address, 1);
27
+ return i2cRead(this._bus);
28
+ }
29
+
30
+ writeBytes(register: number, data: number[] | Uint8Array): void {
31
+ include("<Wire.h>");
32
+ i2cBeginTx(this._bus, this._address);
33
+ i2cWrite(this._bus, register);
34
+ i2cWriteBuffer(this._bus, data);
35
+ i2cEndTx(this._bus, true);
36
+ }
37
+
38
+ readBytes(register: number, count: number): Uint8Array {
39
+ include("<Wire.h>");
40
+ i2cBeginTx(this._bus, this._address);
41
+ i2cWrite(this._bus, register);
42
+ i2cEndTx(this._bus, false);
43
+ i2cRequestFrom(this._bus, this._address, count, true);
44
+ rawCpp(`static uint8_t __buf[${count}];`);
45
+ rawCpp(`for (int __i = 0; __i < ${count}; __i++) __buf[__i] = ${this._bus}.read();`);
46
+ rawCpp(`return __buf;`);
47
+ return new Uint8Array(count);
48
+ }
49
+ }
50
+
51
+ export class I2CBus {
52
+ static readonly __includes = ["<Wire.h>"];
53
+ private _bus: string;
54
+
55
+ constructor(bus: string) {
56
+ this._bus = bus;
57
+ }
58
+
59
+ device(address: number): I2CDevice {
60
+ return new I2CDevice(this._bus, address);
61
+ }
62
+
63
+ begin(): this {
64
+ include("<Wire.h>");
65
+ i2cBegin(this._bus);
66
+ return this;
67
+ }
68
+
69
+ beginSlave(address: number): void {
70
+ i2cBegin(this._bus, address);
71
+ }
72
+
73
+ end(): void {
74
+ i2cEnd(this._bus);
75
+ }
76
+
77
+ setClock(hz: number): void {
78
+ i2cSetClock(this._bus, hz);
79
+ }
80
+
81
+ /** Recover a locked I2C bus by clocking SCL until the stuck slave releases SDA.
82
+ *
83
+ * NOTE: This references the board-defined `SCL` pin macro. All current MCU
84
+ * packages (atmega328p, esp32, esp32c3, esp32c6, esp32s3) export SCL, so
85
+ * this works in practice. A fully portable version would resolve the SCL
86
+ * pin number via a board constant (e.g. peripherals.i2c.0.sclPin), but that
87
+ * requires adding resolved numeric pin fields to the board-constants
88
+ * pipeline — deferred for now. */
89
+ recover(): void {
90
+ include("<Wire.h>");
91
+ rawCpp(`pinMode(SCL, OUTPUT);`);
92
+ rawCpp(`for (int i = 0; i < 16; i++) {`);
93
+ rawCpp(` digitalWrite(SCL, LOW);`);
94
+ rawCpp(` delayMicroseconds(10);`);
95
+ rawCpp(` digitalWrite(SCL, HIGH);`);
96
+ rawCpp(` delayMicroseconds(10);`);
97
+ rawCpp(`}`);
98
+ rawCpp(`${this._bus}.begin();`);
99
+ }
100
+
101
+ take(): this | null {
102
+ include("<Wire.h>");
103
+ return this;
104
+ }
105
+
106
+ release(): void {
107
+ // No-op for standard Arduino.
108
+ }
109
+
110
+ writeByte(address: number, register: number, value: number): void {
111
+ i2cBeginTx(this._bus, address);
112
+ i2cWrite(this._bus, register);
113
+ i2cWrite(this._bus, value);
114
+ i2cEndTx(this._bus, true);
115
+ }
116
+
117
+ readByte(address: number, register: number): number {
118
+ i2cBeginTx(this._bus, address);
119
+ i2cWrite(this._bus, register);
120
+ i2cEndTx(this._bus, false);
121
+ i2cRequestFrom(this._bus, address, 1);
122
+ return i2cRead(this._bus);
123
+ }
124
+
125
+ // Low-level Wire API pass-through methods
126
+ beginTransmission(address: number): void {
127
+ i2cBeginTx(this._bus, address);
128
+ }
129
+
130
+ write(data: number | number[] | Uint8Array): void {
131
+ i2cWrite(this._bus, data);
132
+ }
133
+
134
+ endTransmission(stop?: boolean): number {
135
+ return i2cEndTx(this._bus, stop ?? true);
136
+ }
137
+
138
+ requestFrom(address: number, quantity: number, stop?: boolean): number {
139
+ return i2cRequestFrom(this._bus, address, quantity, stop ?? true);
140
+ }
141
+
142
+ available(): number {
143
+ return i2cAvailable(this._bus);
144
+ }
145
+
146
+ read(): number {
147
+ return i2cRead(this._bus);
148
+ }
149
+ }
150
+
151
+
152
+ /** Map TypeCAD I2C instance number to Arduino C++ object name. I2C0→Wire, I2C1→Wire1 */
153
+ export function i2cName(instance: number): string {
154
+ return instance === 0 ? "Wire" : `Wire${instance}`;
155
+ }
package/src/include.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Compile-time function: adds a C++ #include header to the generated output.
3
+ * At runtime (tests, type-checking) this is a no-op.
4
+ */
5
+ export function include(_text: string): void {}
package/src/index.ts ADDED
@@ -0,0 +1,48 @@
1
+ // Re-export commonly-used types so consumers can import everything from @typecad/hal
2
+ //
3
+ // Runtime-contract interfaces (BasePin, II2CBus, ISPIBus, ISerialPort, the
4
+ // status enums, capability guards, PinCapabilityFlags, IToneAttachment, ...)
5
+ // now live in @typecad/simulator. Import them from there.
6
+ export type { DigitalValue, AnalogValue } from './types.js';
7
+ export { PinMode, InterruptMode } from './types.js';
8
+ export type { IPinGroup, PinGroupMember } from './types.js';
9
+ export { createPinGroup } from './types.js';
10
+
11
+ export type { InterruptHandler } from './types.js';
12
+
13
+ export type { ArchitectureIdentifier } from './types.js';
14
+
15
+ // Protocol-shape types (re-exported downstream by @typecad/framework-arduino)
16
+ export type { I2CAddress } from './types.js';
17
+ export type { SPIBitOrder, SPIMode, SPISettings } from './types.js';
18
+
19
+ export { include } from './include.js';
20
+ export { board } from './board.js';
21
+ export { callback } from './callback.js';
22
+ export { rawCpp, boardResolve } from './emit.js';
23
+ export { HIGH, LOW, OUTPUT, INPUT, INPUT_PULLUP, INPUT_PULLDOWN, OUTPUT_OPEN_DRAIN, ANALOG, LED_BUILTIN, LSBFIRST, MSBFIRST, WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S } from './constants.js';
24
+ export { delay, millis, micros, delayMicroseconds, map, constrain, TimingClass, Timing } from './timing.js';
25
+ export { freeHeap, setInterval, setTimeout, clearInterval, clearTimeout } from './timing.js';
26
+ export { abs, min, max, NumClass, Num, MapChain, ConstrainChain } from './math.js';
27
+ export { Pulse, pulseIn, pulseInLong } from './pulse.js';
28
+ export { Shift, shiftIn, shiftOut } from './shift.js';
29
+ export { Random } from './random.js';
30
+ export { randomSeed, random } from './random.js';
31
+ export { noInterrupts, interrupts, attachInterrupt, detachInterrupt } from './interrupts.js';
32
+ export { Pin, OutputPin, InputPin, ToneChain } from './gpio.js';
33
+ export { I2CBus, I2CDevice, i2cName } from './i2c.js';
34
+ export { SPIBus, SPIDevice, spiName } from './spi.js';
35
+ export { SerialPort, serialName } from './uart.js';
36
+ export { createHALInstances } from './utils.js';
37
+ // Register-mapped struct decorators (compile-time markers, erased by transpiler)
38
+ export type { Bit, Bits } from './register.js';
39
+ export { register, bits } from './register.js';
40
+ export { EEPROMClass, EEPROM } from './eeprom.js';
41
+ export { WDTClass, WDT } from './wdt.js';
42
+ export { ADCClass, ADC } from './adc.js';
43
+ export { DACClass, DAC } from './dac.js';
44
+ export { PreferencesClass, Preferences } from './preferences.js';
45
+ export { HardwareTimer, Timer0, Timer1, Timer2 } from './timer.js';
46
+ export { FSClass, FS } from './fs.js';
47
+ export { PowerClass, Power } from './power.js';
48
+ export { AsyncClass, Async } from './async.js';
@@ -0,0 +1,35 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @typecad/hal — Interrupt helpers
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import { interruptAttach, interruptDetach } from './emit.js';
6
+ import { callback } from './callback.js';
7
+ import type { InterruptHandler, InterruptMode } from './types.js';
8
+
9
+ /**
10
+ * Globally disable interrupts.
11
+ */
12
+ export function noInterrupts(): void {}
13
+
14
+ /**
15
+ * Re-enable interrupts after `noInterrupts()`.
16
+ */
17
+ export function interrupts(): void {}
18
+
19
+ /**
20
+ * Attach an interrupt handler to a pin.
21
+ */
22
+ export function attachInterrupt(
23
+ pin: number,
24
+ handler: InterruptHandler,
25
+ mode: InterruptMode,
26
+ ): void {
27
+ interruptAttach(pin, callback(handler), mode);
28
+ }
29
+
30
+ /**
31
+ * Detach a previously attached interrupt.
32
+ */
33
+ export function detachInterrupt(pin: number): void {
34
+ interruptDetach(pin);
35
+ }
package/src/math.ts ADDED
@@ -0,0 +1,32 @@
1
+ export class MapChain {
2
+ constructor(value: number) {}
3
+ from(low: number, high: number): MapChain { return this; }
4
+ to(low: number, high: number): number { return 0; }
5
+ toPercent(): number { return 0; }
6
+ toByte(): number { return 0; }
7
+ }
8
+
9
+ export class ConstrainChain {
10
+ constructor(value: number) {}
11
+ between(low: number, high: number): number { return 0; }
12
+ }
13
+
14
+ export class NumClass {
15
+ // No __instance_name — Num methods must NOT be intercepted by the HAL
16
+ // resolver. They pass through as bare C++ calls (Num.abs(-7)), which the
17
+ // strategy's __tc_Num polyfill struct provides. The strategy post-processes
18
+ // the output to rename Num.abs( → Num._abs( to match the polyfill's
19
+ // parenthesized method names (which avoid macro collisions with Arduino's
20
+ // abs/min/max macros). See strategy.ts __tc_Num struct + the rewrite regex.
21
+ abs(x: number): number { return 0; }
22
+ min(a: number, b: number): number { return 0; }
23
+ max(a: number, b: number): number { return 0; }
24
+ constrain(value: number): ConstrainChain { return new ConstrainChain(value); }
25
+ map(value: number): MapChain { return new MapChain(value); }
26
+ }
27
+
28
+ export const Num = new NumClass();
29
+
30
+ export function abs(x: number): number { return 0; }
31
+ export function min(a: number, b: number): number { return 0; }
32
+ export function max(a: number, b: number): number { return 0; }
package/src/power.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { powerDeepSleep, powerLightSleep, powerSetCpuFrequency } from './emit.js';
2
+
3
+ /**
4
+ * PowerClass provides control over MCU power states and clock frequencies.
5
+ *
6
+ * The arch guard (ESP32 family vs AVR) lives in the strategy, not here — it
7
+ * relies on the FQBN-derived architecture which is always available at
8
+ * transpile time, unlike `board("architecture")` which needs a board package.
9
+ */
10
+ export class PowerClass {
11
+ static readonly __instance_name = "Power";
12
+
13
+ deepSleep(ms: number): void {
14
+ powerDeepSleep(ms);
15
+ }
16
+
17
+ lightSleep(): void {
18
+ powerLightSleep();
19
+ }
20
+
21
+ setCpuFrequency(mhz: number): void {
22
+ powerSetCpuFrequency(mhz);
23
+ }
24
+ }
25
+
26
+ export const Power = new PowerClass();
@@ -0,0 +1,58 @@
1
+ import { rawCpp } from './emit.js';
2
+
3
+ export class PreferencesClass {
4
+ static readonly __instance_name = "Preferences";
5
+ // NOTE: no __includes here. The transpiler emits singleton __includes on
6
+ // every architecture with no filtering, and <Preferences.h> is ESP32-only —
7
+ // adding it would break AVR builds. The class is ESP32-only by convention.
8
+
9
+ begin(name: string, readOnly: boolean = false): void {
10
+ rawCpp(`Preferences.begin(${name}.c_str(), ${readOnly});`);
11
+ }
12
+ end(): void {
13
+ rawCpp(`Preferences.end();`);
14
+ }
15
+ clear(): void {
16
+ rawCpp(`Preferences.clear();`);
17
+ }
18
+ remove(key: string): void {
19
+ rawCpp(`Preferences.remove(${key}.c_str());`);
20
+ }
21
+ putInt(key: string, value: number): void {
22
+ rawCpp(`Preferences.putInt(${key}.c_str(), ${value});`);
23
+ }
24
+ getInt(key: string, defaultValue: number = 0): number {
25
+ rawCpp(`return Preferences.getInt(${key}.c_str(), ${defaultValue});`);
26
+ return 0;
27
+ }
28
+ putUInt(key: string, value: number): void {
29
+ rawCpp(`Preferences.putUInt(${key}.c_str(), ${value});`);
30
+ }
31
+ getUInt(key: string, defaultValue: number = 0): number {
32
+ rawCpp(`return Preferences.getUInt(${key}.c_str(), ${defaultValue});`);
33
+ return 0;
34
+ }
35
+ putFloat(key: string, value: number): void {
36
+ rawCpp(`Preferences.putFloat(${key}.c_str(), ${value});`);
37
+ }
38
+ getFloat(key: string, defaultValue: number = 0): number {
39
+ rawCpp(`return Preferences.getFloat(${key}.c_str(), ${defaultValue});`);
40
+ return 0;
41
+ }
42
+ putBool(key: string, value: boolean): void {
43
+ rawCpp(`Preferences.putBool(${key}.c_str(), ${value});`);
44
+ }
45
+ getBool(key: string, defaultValue: boolean = false): boolean {
46
+ rawCpp(`return Preferences.getBool(${key}.c_str(), ${defaultValue});`);
47
+ return false;
48
+ }
49
+ putString(key: string, value: string): void {
50
+ rawCpp(`Preferences.putString(${key}.c_str(), ${value}.c_str());`);
51
+ }
52
+ getString(key: string, defaultValue: string = ""): string {
53
+ rawCpp(`return Preferences.getString(${key}.c_str(), ${defaultValue}.c_str());`);
54
+ return "";
55
+ }
56
+ }
57
+
58
+ export const Preferences = new PreferencesClass();