@typecad/hal 1.0.0-alpha.3 → 1.0.0-alpha.6
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/dist/emit.d.ts +17 -0
- package/dist/emit.js +17 -0
- package/dist/i2c.d.ts +7 -0
- package/dist/i2c.js +15 -4
- package/dist/register.d.ts +12 -4
- package/dist/register.js +18 -1
- package/dist/spi.js +10 -7
- package/package.json +4 -4
- package/src/emit.ts +17 -0
- package/src/i2c.ts +16 -4
- package/src/register.ts +16 -4
- package/src/spi.ts +10 -7
package/dist/emit.d.ts
CHANGED
|
@@ -53,6 +53,15 @@ export declare function i2cRequestFrom(bus: string, address: number, quantity: n
|
|
|
53
53
|
export declare function i2cAvailable(bus: string): number;
|
|
54
54
|
/** Read a byte from I2C. */
|
|
55
55
|
export declare function i2cRead(bus: string): number;
|
|
56
|
+
/**
|
|
57
|
+
* Drain `count` bytes requested from the I2C bus into a caller-provided buffer.
|
|
58
|
+
* Semantic primitive: lowers to the `i2c.read_buffer` HAL op. The `buffer`
|
|
59
|
+
* argument is emitted as a placeholder (`__HAL_READ_BUF__`) that the var-init
|
|
60
|
+
* transformer rewrites to the caller's own buffer variable, so bytes land in
|
|
61
|
+
* the `uint8_t data[N]` declared in user scope — NOT an internal temp that
|
|
62
|
+
* decays to a pointer on return. Keeps `data.length` / `data[i]` valid.
|
|
63
|
+
*/
|
|
64
|
+
export declare function i2cReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void;
|
|
56
65
|
/** Initialize SPI bus. */
|
|
57
66
|
export declare function spiBegin(bus: string): void;
|
|
58
67
|
/** Disable SPI bus. */
|
|
@@ -67,6 +76,14 @@ export declare function spiEndTx(bus: string): void;
|
|
|
67
76
|
export declare function spiCsLow(pin: number | string): void;
|
|
68
77
|
/** Set SPI chip-select pin HIGH. */
|
|
69
78
|
export declare function spiCsHigh(pin: number | string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Read `count` bytes from the SPI bus into a caller-provided buffer by clocking
|
|
81
|
+
* dummy (0x00) transfers. Semantic primitive: lowers to the `spi.read_buffer`
|
|
82
|
+
* HAL op (per-byte `bus.transfer(0)` read loop). The `buffer` placeholder is
|
|
83
|
+
* rewritten to the caller's variable. Mirrors i2cReadBuffer. The caller is
|
|
84
|
+
* responsible for asserting/de-asserting chip-select around it.
|
|
85
|
+
*/
|
|
86
|
+
export declare function spiReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void;
|
|
70
87
|
/** Set SPI data mode. */
|
|
71
88
|
export declare function spiSetMode(bus: string, mode: number): void;
|
|
72
89
|
/** Set SPI bit order. */
|
package/dist/emit.js
CHANGED
|
@@ -85,6 +85,15 @@ export function i2cRequestFrom(bus, address, quantity, stop) { return 0; }
|
|
|
85
85
|
export function i2cAvailable(bus) { return 0; }
|
|
86
86
|
/** Read a byte from I2C. */
|
|
87
87
|
export function i2cRead(bus) { return 0; }
|
|
88
|
+
/**
|
|
89
|
+
* Drain `count` bytes requested from the I2C bus into a caller-provided buffer.
|
|
90
|
+
* Semantic primitive: lowers to the `i2c.read_buffer` HAL op. The `buffer`
|
|
91
|
+
* argument is emitted as a placeholder (`__HAL_READ_BUF__`) that the var-init
|
|
92
|
+
* transformer rewrites to the caller's own buffer variable, so bytes land in
|
|
93
|
+
* the `uint8_t data[N]` declared in user scope — NOT an internal temp that
|
|
94
|
+
* decays to a pointer on return. Keeps `data.length` / `data[i]` valid.
|
|
95
|
+
*/
|
|
96
|
+
export function i2cReadBuffer(bus, count, buffer) { }
|
|
88
97
|
// ---------------------------------------------------------------------------
|
|
89
98
|
// SPI — serial peripheral interface
|
|
90
99
|
// ---------------------------------------------------------------------------
|
|
@@ -102,6 +111,14 @@ export function spiEndTx(bus) { }
|
|
|
102
111
|
export function spiCsLow(pin) { }
|
|
103
112
|
/** Set SPI chip-select pin HIGH. */
|
|
104
113
|
export function spiCsHigh(pin) { }
|
|
114
|
+
/**
|
|
115
|
+
* Read `count` bytes from the SPI bus into a caller-provided buffer by clocking
|
|
116
|
+
* dummy (0x00) transfers. Semantic primitive: lowers to the `spi.read_buffer`
|
|
117
|
+
* HAL op (per-byte `bus.transfer(0)` read loop). The `buffer` placeholder is
|
|
118
|
+
* rewritten to the caller's variable. Mirrors i2cReadBuffer. The caller is
|
|
119
|
+
* responsible for asserting/de-asserting chip-select around it.
|
|
120
|
+
*/
|
|
121
|
+
export function spiReadBuffer(bus, count, buffer) { }
|
|
105
122
|
/** Set SPI data mode. */
|
|
106
123
|
export function spiSetMode(bus, mode) { }
|
|
107
124
|
/** Set SPI bit order. */
|
package/dist/i2c.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ export declare class I2CDevice {
|
|
|
2
2
|
private _bus;
|
|
3
3
|
private _address;
|
|
4
4
|
constructor(bus: string, address: number);
|
|
5
|
+
/** The 7-bit I2C address this accessor targets. Exposed so I2CDevice
|
|
6
|
+
* structurally satisfies the @typecad/simulator II2CDeviceAccessor contract
|
|
7
|
+
* (which declares `readonly address`), letting the same driver function be
|
|
8
|
+
* typed against the contract and accept either a real board device or a
|
|
9
|
+
* simulated one. The transpiler strips HAL class bodies to IR, so this
|
|
10
|
+
* getter carries no runtime cost in the generated C++. */
|
|
11
|
+
get address(): number;
|
|
5
12
|
writeByte(register: number, value: number): void;
|
|
6
13
|
readByte(register: number): number;
|
|
7
14
|
writeBytes(register: number, data: number[] | Uint8Array): void;
|
package/dist/i2c.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, rawCpp } from './emit.js';
|
|
1
|
+
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, i2cReadBuffer, rawCpp } from './emit.js';
|
|
2
2
|
import { include } from './include.js';
|
|
3
3
|
export class I2CDevice {
|
|
4
4
|
constructor(bus, address) {
|
|
5
5
|
this._bus = bus;
|
|
6
6
|
this._address = address;
|
|
7
7
|
}
|
|
8
|
+
/** The 7-bit I2C address this accessor targets. Exposed so I2CDevice
|
|
9
|
+
* structurally satisfies the @typecad/simulator II2CDeviceAccessor contract
|
|
10
|
+
* (which declares `readonly address`), letting the same driver function be
|
|
11
|
+
* typed against the contract and accept either a real board device or a
|
|
12
|
+
* simulated one. The transpiler strips HAL class bodies to IR, so this
|
|
13
|
+
* getter carries no runtime cost in the generated C++. */
|
|
14
|
+
get address() {
|
|
15
|
+
return this._address;
|
|
16
|
+
}
|
|
8
17
|
writeByte(register, value) {
|
|
9
18
|
include("<Wire.h>");
|
|
10
19
|
i2cBeginTx(this._bus, this._address);
|
|
@@ -33,9 +42,11 @@ export class I2CDevice {
|
|
|
33
42
|
i2cWrite(this._bus, register);
|
|
34
43
|
i2cEndTx(this._bus, false);
|
|
35
44
|
i2cRequestFrom(this._bus, this._address, count, true);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
rawCpp
|
|
45
|
+
// Drain the requested bytes into the caller's buffer (declared by the
|
|
46
|
+
// Uint8Array return marker as `uint8_t data[count]`). Using the semantic
|
|
47
|
+
// primitive — NOT rawCpp — keeps the buffer in user scope so it survives
|
|
48
|
+
// the return (no decayed pointer) and `data.length` / `data[i]` work.
|
|
49
|
+
i2cReadBuffer(this._bus, count, new Uint8Array(count));
|
|
39
50
|
return new Uint8Array(count);
|
|
40
51
|
}
|
|
41
52
|
}
|
package/dist/register.d.ts
CHANGED
|
@@ -4,8 +4,16 @@ export type Bit = 0 | 1;
|
|
|
4
4
|
* the bit width for documentation only; the value is the raw field contents. */
|
|
5
5
|
export type Bits<N extends number = number> = number;
|
|
6
6
|
/** Class decorator marking a struct as a memory-mapped register at `address`.
|
|
7
|
-
* Erased at transpile time — the class becomes a `volatile uint32_t*`.
|
|
8
|
-
|
|
7
|
+
* Erased at transpile time — the class becomes a `volatile uint32_t*`.
|
|
8
|
+
*
|
|
9
|
+
* These carry real (inert) runtime bodies rather than `declare`, so the
|
|
10
|
+
* `export { register, bits }` re-export in index.ts resolves under Node's ESM
|
|
11
|
+
* loader, which validates that re-exported bindings exist at runtime. They are
|
|
12
|
+
* never invoked: the cuttlefish transpiler detects them by name and lowers the
|
|
13
|
+
* decorated struct away, so these stubs are only reached when the decorator
|
|
14
|
+
* source is imported without transpilation (e.g. host-side tests). */
|
|
15
|
+
export declare function register(_address: number): ClassDecorator;
|
|
9
16
|
/** Property decorator carrying the bit range [lo, hi] (inclusive) of a field
|
|
10
|
-
* within its register. Erased at transpile time.
|
|
11
|
-
|
|
17
|
+
* within its register. Erased at transpile time. See `register` for why these
|
|
18
|
+
* have runtime bodies. */
|
|
19
|
+
export declare function bits(_hi: number, _lo: number): PropertyDecorator;
|
package/dist/register.js
CHANGED
|
@@ -18,4 +18,21 @@
|
|
|
18
18
|
// USART1.UE = 1; // (*USART1 & ~1UL) | ((1 & 1UL) << 0)
|
|
19
19
|
// const parity = USART1.PS; // ((*USART1 >> 8) & ((1UL << 2) - 1))
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
|
-
|
|
21
|
+
/** Class decorator marking a struct as a memory-mapped register at `address`.
|
|
22
|
+
* Erased at transpile time — the class becomes a `volatile uint32_t*`.
|
|
23
|
+
*
|
|
24
|
+
* These carry real (inert) runtime bodies rather than `declare`, so the
|
|
25
|
+
* `export { register, bits }` re-export in index.ts resolves under Node's ESM
|
|
26
|
+
* loader, which validates that re-exported bindings exist at runtime. They are
|
|
27
|
+
* never invoked: the cuttlefish transpiler detects them by name and lowers the
|
|
28
|
+
* decorated struct away, so these stubs are only reached when the decorator
|
|
29
|
+
* source is imported without transpilation (e.g. host-side tests). */
|
|
30
|
+
export function register(_address) {
|
|
31
|
+
return () => { };
|
|
32
|
+
}
|
|
33
|
+
/** Property decorator carrying the bit range [lo, hi] (inclusive) of a field
|
|
34
|
+
* within its register. Erased at transpile time. See `register` for why these
|
|
35
|
+
* have runtime bodies. */
|
|
36
|
+
export function bits(_hi, _lo) {
|
|
37
|
+
return () => { };
|
|
38
|
+
}
|
package/dist/spi.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spiBegin, spiEnd, spiTransfer, spiBeginTx, spiEndTx, spiCsLow, spiCsHigh, spiSetMode, spiSetBitOrder, rawCpp } from './emit.js';
|
|
1
|
+
import { spiBegin, spiEnd, spiTransfer, spiBeginTx, spiEndTx, spiCsLow, spiCsHigh, spiSetMode, spiSetBitOrder, spiReadBuffer, rawCpp } from './emit.js';
|
|
2
2
|
import { include } from './include.js';
|
|
3
3
|
export class SPIDevice {
|
|
4
4
|
constructor(bus, chipSelect) {
|
|
@@ -21,12 +21,15 @@ export class SPIDevice {
|
|
|
21
21
|
}
|
|
22
22
|
readRegister(register, count) {
|
|
23
23
|
include("<SPI.h>");
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
rawCpp
|
|
29
|
-
|
|
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);
|
|
30
33
|
return new Uint8Array(count);
|
|
31
34
|
}
|
|
32
35
|
writeRegister(register, value) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typecad/hal",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.6",
|
|
4
4
|
"description": "TypeCAD hardware abstraction layer — GPIO, I2C, SPI, UART as regular TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
},
|
|
50
50
|
"author": "typecad0",
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@typecad/expect": "1.0.0-alpha.
|
|
53
|
-
"@typecad/board-arduino-uno": "1.0.0-alpha.
|
|
54
|
-
"@typecad/mcu-atmega328p": "1.0.0-alpha.
|
|
52
|
+
"@typecad/expect": "1.0.0-alpha.6",
|
|
53
|
+
"@typecad/board-arduino-uno": "1.0.0-alpha.6",
|
|
54
|
+
"@typecad/mcu-atmega328p": "1.0.0-alpha.6"
|
|
55
55
|
},
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"exports": {
|
package/src/emit.ts
CHANGED
|
@@ -99,6 +99,15 @@ export function i2cRequestFrom(bus: string, address: number, quantity: number, s
|
|
|
99
99
|
export function i2cAvailable(bus: string): number { return 0; }
|
|
100
100
|
/** Read a byte from I2C. */
|
|
101
101
|
export function i2cRead(bus: string): number { return 0; }
|
|
102
|
+
/**
|
|
103
|
+
* Drain `count` bytes requested from the I2C bus into a caller-provided buffer.
|
|
104
|
+
* Semantic primitive: lowers to the `i2c.read_buffer` HAL op. The `buffer`
|
|
105
|
+
* argument is emitted as a placeholder (`__HAL_READ_BUF__`) that the var-init
|
|
106
|
+
* transformer rewrites to the caller's own buffer variable, so bytes land in
|
|
107
|
+
* the `uint8_t data[N]` declared in user scope — NOT an internal temp that
|
|
108
|
+
* decays to a pointer on return. Keeps `data.length` / `data[i]` valid.
|
|
109
|
+
*/
|
|
110
|
+
export function i2cReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void {}
|
|
102
111
|
|
|
103
112
|
// ---------------------------------------------------------------------------
|
|
104
113
|
// SPI — serial peripheral interface
|
|
@@ -118,6 +127,14 @@ export function spiEndTx(bus: string): void {}
|
|
|
118
127
|
export function spiCsLow(pin: number | string): void {}
|
|
119
128
|
/** Set SPI chip-select pin HIGH. */
|
|
120
129
|
export function spiCsHigh(pin: number | string): void {}
|
|
130
|
+
/**
|
|
131
|
+
* Read `count` bytes from the SPI bus into a caller-provided buffer by clocking
|
|
132
|
+
* dummy (0x00) transfers. Semantic primitive: lowers to the `spi.read_buffer`
|
|
133
|
+
* HAL op (per-byte `bus.transfer(0)` read loop). The `buffer` placeholder is
|
|
134
|
+
* rewritten to the caller's variable. Mirrors i2cReadBuffer. The caller is
|
|
135
|
+
* responsible for asserting/de-asserting chip-select around it.
|
|
136
|
+
*/
|
|
137
|
+
export function spiReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void {}
|
|
121
138
|
/** Set SPI data mode. */
|
|
122
139
|
export function spiSetMode(bus: string, mode: number): void {}
|
|
123
140
|
/** Set SPI bit order. */
|
package/src/i2c.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, rawCpp } from './emit.js';
|
|
1
|
+
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, i2cReadBuffer, rawCpp } from './emit.js';
|
|
2
2
|
import { include } from './include.js';
|
|
3
3
|
|
|
4
4
|
export class I2CDevice {
|
|
@@ -10,6 +10,16 @@ export class I2CDevice {
|
|
|
10
10
|
this._address = address;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/** The 7-bit I2C address this accessor targets. Exposed so I2CDevice
|
|
14
|
+
* structurally satisfies the @typecad/simulator II2CDeviceAccessor contract
|
|
15
|
+
* (which declares `readonly address`), letting the same driver function be
|
|
16
|
+
* typed against the contract and accept either a real board device or a
|
|
17
|
+
* simulated one. The transpiler strips HAL class bodies to IR, so this
|
|
18
|
+
* getter carries no runtime cost in the generated C++. */
|
|
19
|
+
get address(): number {
|
|
20
|
+
return this._address;
|
|
21
|
+
}
|
|
22
|
+
|
|
13
23
|
writeByte(register: number, value: number): void {
|
|
14
24
|
include("<Wire.h>");
|
|
15
25
|
i2cBeginTx(this._bus, this._address);
|
|
@@ -41,9 +51,11 @@ export class I2CDevice {
|
|
|
41
51
|
i2cWrite(this._bus, register);
|
|
42
52
|
i2cEndTx(this._bus, false);
|
|
43
53
|
i2cRequestFrom(this._bus, this._address, count, true);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
rawCpp
|
|
54
|
+
// Drain the requested bytes into the caller's buffer (declared by the
|
|
55
|
+
// Uint8Array return marker as `uint8_t data[count]`). Using the semantic
|
|
56
|
+
// primitive — NOT rawCpp — keeps the buffer in user scope so it survives
|
|
57
|
+
// the return (no decayed pointer) and `data.length` / `data[i]` work.
|
|
58
|
+
i2cReadBuffer(this._bus, count, new Uint8Array(count));
|
|
47
59
|
return new Uint8Array(count);
|
|
48
60
|
}
|
|
49
61
|
}
|
package/src/register.ts
CHANGED
|
@@ -27,9 +27,21 @@ export type Bit = 0 | 1;
|
|
|
27
27
|
export type Bits<N extends number = number> = number;
|
|
28
28
|
|
|
29
29
|
/** Class decorator marking a struct as a memory-mapped register at `address`.
|
|
30
|
-
* Erased at transpile time — the class becomes a `volatile uint32_t*`.
|
|
31
|
-
|
|
30
|
+
* Erased at transpile time — the class becomes a `volatile uint32_t*`.
|
|
31
|
+
*
|
|
32
|
+
* These carry real (inert) runtime bodies rather than `declare`, so the
|
|
33
|
+
* `export { register, bits }` re-export in index.ts resolves under Node's ESM
|
|
34
|
+
* loader, which validates that re-exported bindings exist at runtime. They are
|
|
35
|
+
* never invoked: the cuttlefish transpiler detects them by name and lowers the
|
|
36
|
+
* decorated struct away, so these stubs are only reached when the decorator
|
|
37
|
+
* source is imported without transpilation (e.g. host-side tests). */
|
|
38
|
+
export function register(_address: number): ClassDecorator {
|
|
39
|
+
return () => {};
|
|
40
|
+
}
|
|
32
41
|
|
|
33
42
|
/** Property decorator carrying the bit range [lo, hi] (inclusive) of a field
|
|
34
|
-
* within its register. Erased at transpile time.
|
|
35
|
-
|
|
43
|
+
* within its register. Erased at transpile time. See `register` for why these
|
|
44
|
+
* have runtime bodies. */
|
|
45
|
+
export function bits(_hi: number, _lo: number): PropertyDecorator {
|
|
46
|
+
return () => {};
|
|
47
|
+
}
|
package/src/spi.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spiBegin, spiEnd, spiTransfer, spiBeginTx, spiEndTx, spiCsLow, spiCsHigh, spiSetMode, spiSetBitOrder, rawCpp } from './emit.js';
|
|
1
|
+
import { spiBegin, spiEnd, spiTransfer, spiBeginTx, spiEndTx, spiCsLow, spiCsHigh, spiSetMode, spiSetBitOrder, spiReadBuffer, rawCpp } from './emit.js';
|
|
2
2
|
import { include } from './include.js';
|
|
3
3
|
import type { Pin } from './gpio.js';
|
|
4
4
|
import type { SPIMode, SPISettings } from './types.js';
|
|
@@ -30,12 +30,15 @@ export class SPIDevice {
|
|
|
30
30
|
|
|
31
31
|
readRegister(register: number, count: number): Uint8Array {
|
|
32
32
|
include("<SPI.h>");
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
rawCpp
|
|
38
|
-
|
|
33
|
+
spiCsLow(this._cs);
|
|
34
|
+
spiTransfer(this._bus, register);
|
|
35
|
+
// Clock `count` dummy bytes and drain them into the caller's buffer
|
|
36
|
+
// (declared by the Uint8Array return marker as `uint8_t data[count]`).
|
|
37
|
+
// Using the semantic primitive — NOT rawCpp — keeps the buffer in user
|
|
38
|
+
// scope so it survives the return (no decayed pointer) and `data.length`
|
|
39
|
+
// / `data[i]` work, mirroring I2CDevice.readBytes.
|
|
40
|
+
spiReadBuffer(this._bus, count, new Uint8Array(count));
|
|
41
|
+
spiCsHigh(this._cs);
|
|
39
42
|
return new Uint8Array(count);
|
|
40
43
|
}
|
|
41
44
|
|