stm32f4-emu 0.1.0

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/site/netsim.js ADDED
@@ -0,0 +1,212 @@
1
+ // In-browser network simulator: answers the eth_http firmware's DHCP, TCP
2
+ // and HTTP traffic with canned replies (no real stack, no gateway needed).
3
+ //
4
+ // Mirrors the openhw-local-gateway roles:
5
+ // server MAC = 5a:94:ef:e4:0c:dd (the firmware's compile-time gw_mac)
6
+ // server IP = 192.168.4.1, offered client IP = 192.168.4.2
7
+ // TCP target = <client IP>:8092 (HTTP)
8
+
9
+ export function createNetSim({ log = () => {} } = {}) {
10
+ const SERVER_MAC = [0x5a, 0x94, 0xef, 0xe4, 0x0c, 0xdd];
11
+ const CLIENT_MAC = [0x02, 0x00, 0x00, 0x00, 0x00, 0x01];
12
+ const SERVER_IP = [192, 168, 4, 1];
13
+ const CLIENT_IP = [192, 168, 4, 2];
14
+ const MASK = [255, 255, 255, 0];
15
+ const HTTP_PORT = 8092;
16
+ const HTTP_BODY =
17
+ 'HTTP/1.1 200 OK\r\n' +
18
+ 'Content-Length: 29\r\n' +
19
+ 'Connection: close\r\n\r\n' +
20
+ 'Hello from openhw HTTP server';
21
+
22
+ let clientMac = CLIENT_MAC.slice();
23
+ let srvSeq = 0x10000000; // server ISN
24
+ let clientSeq = 0; // learned from the client SYN
25
+ let lastMsgType = 0;
26
+
27
+ const stats = { tx: 0, rx: 0, dhcpOffers: 0, dhcpAcks: 0, synAcks: 0, httpResponses: 0 };
28
+
29
+ const cksum = (bytes) => {
30
+ let sum = 0;
31
+ for (let i = 0; i < bytes.length; i += 2) {
32
+ const w = (bytes[i] << 8) | (i + 1 < bytes.length ? bytes[i + 1] : 0);
33
+ sum += w;
34
+ }
35
+ while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
36
+ return (~sum) & 0xffff;
37
+ };
38
+
39
+ // Build a complete Ethernet+IP(+UDP/TCP) frame with correct IP checksum.
40
+ const buildFrame = (dstIp, proto, udpOrTcpPayload) => {
41
+ const ipLen = 20 + udpOrTcpPayload.length;
42
+ const f = new Uint8Array(14 + ipLen);
43
+ f.set(dstIp === 255 ? [255,255,255,255,255,255] : clientMac, 0);
44
+ f.set(SERVER_MAC, 6);
45
+ f[12] = 0x08; f[13] = 0x00;
46
+ const ip = 14;
47
+ f[ip] = 0x45; f[ip + 1] = 0;
48
+ f[ip + 2] = ipLen >> 8; f[ip + 3] = ipLen & 0xff;
49
+ f[ip + 8] = 128; f[ip + 9] = proto;
50
+ f.set(SERVER_IP, ip + 12);
51
+ f.set(dstIp, ip + 16);
52
+ const ck = cksum(f.subarray(ip, ip + 20));
53
+ f[ip + 10] = ck >> 8; f[ip + 11] = ck & 0xff;
54
+ f.set(udpOrTcpPayload, ip + 20);
55
+ return f;
56
+ };
57
+
58
+ // ── DHCP reply (Offer or Ack) ──
59
+ const dhcpReply = (req, msgType) => {
60
+ // BOOTP fixed part
61
+ const bootp = new Uint8Array(300);
62
+ const xid = (req[4] << 24) | (req[5] << 16) | (req[6] << 8) | req[7];
63
+ bootp[0] = 2; // op = reply
64
+ bootp[1] = 1; // htype = ethernet
65
+ bootp[2] = 6; // hlen
66
+ bootp[4] = xid >> 24; bootp[5] = xid >> 16; bootp[6] = xid >> 8; bootp[7] = xid;
67
+ bootp[8] = 0x80; bootp[9] = 0x00; // broadcast flag
68
+ bootp.set(CLIENT_IP, 16); // yiaddr
69
+ bootp.set(SERVER_IP, 20); // siaddr
70
+ // chaddr = client's chaddr (12 bytes: MAC + 6 pad)
71
+ bootp.set(req.subarray(28, 40), 28);
72
+ bootp.set([0x63, 0x82, 0x53, 0x63], 236); // magic cookie
73
+ const opts = [53, 1, msgType,
74
+ 1, 4, ...MASK,
75
+ 3, 4, ...SERVER_IP,
76
+ 6, 4, ...SERVER_IP,
77
+ 54, 4, ...SERVER_IP,
78
+ 51, 4, 0, 0, 1, 0x80, // lease 86400
79
+ 255];
80
+ bootp.set(opts, 240);
81
+ // UDP header (src 67, dst 68) + bootp
82
+ const udp = new Uint8Array(8 + bootp.length);
83
+ udp[0] = 0; udp[1] = 67; udp[2] = 0; udp[3] = 68;
84
+ const ulen = 8 + bootp.length;
85
+ udp[4] = ulen >> 8; udp[5] = ulen & 0xff;
86
+ udp.set(bootp, 8);
87
+ return buildFrame(255, 17, udp); // dst IP = broadcast
88
+ };
89
+
90
+ // ── TCP ──
91
+ const tcpFrame = (flags, seq, ack, payload) => {
92
+ const data = payload || new Uint8Array(0);
93
+ const tcp = new Uint8Array(20 + data.length);
94
+ tcp[0] = HTTP_PORT >> 8; tcp[1] = HTTP_PORT & 0xff; // src = server port
95
+ tcp[2] = tcpSrcPort >> 8; tcp[3] = tcpSrcPort & 0xff; // dst = client's ephemeral
96
+ tcp[4] = seq >> 24; tcp[5] = seq >> 16; tcp[6] = seq >> 8; tcp[7] = seq;
97
+ tcp[8] = ack >> 24; tcp[9] = ack >> 16; tcp[10] = ack >> 8; tcp[11] = ack;
98
+ tcp[12] = 0x50; tcp[13] = flags;
99
+ tcp[14] = 0xff; tcp[15] = 0xff;
100
+ tcp.set(data, 20);
101
+ return buildFrame(CLIENT_IP, 6, tcp);
102
+ };
103
+
104
+ let tcpSrcPort = 0; // client ephemeral port, learned from SYN
105
+
106
+ // Parse a TX frame; return an array of reply frames.
107
+ function onTx(frame) {
108
+ stats.tx++;
109
+ const replies = [];
110
+ if (frame.length < 14) return replies;
111
+ const et = (frame[12] << 8) | frame[13];
112
+
113
+ if (et === 0x1234) { // eth_irq_test: echo PING -> PONG
114
+ if (new TextDecoder().decode(frame.subarray(14, 27)).includes('PING')) {
115
+ const r = new Uint8Array(60);
116
+ r.set(frame.subarray(6, 12), 0); // dst = requester MAC
117
+ r.set(frame.subarray(0, 6), 6); // src = requester's dst MAC
118
+ r[12] = 0x12; r[13] = 0x34;
119
+ r.set(new TextEncoder().encode('ETH IRQ PONG'), 14);
120
+ replies.push(r);
121
+ }
122
+ return replies;
123
+ }
124
+
125
+ if (et === 0x0806) { // ARP: answer requests for the server IP
126
+ const a = 14;
127
+ if (frame[a] === 0 && frame[a + 1] === 1 && frame[a + 6] === 0 && frame[a + 7] === 1) {
128
+ const tip = [frame[a + 24], frame[a + 25], frame[a + 26], frame[a + 27]];
129
+ if (tip[0] === SERVER_IP[0] && tip[1] === SERVER_IP[1] && tip[2] === SERVER_IP[2] && tip[3] === SERVER_IP[3]) {
130
+ const r = new Uint8Array(42);
131
+ r.set(frame.subarray(6, 12), 0); // dst = requester MAC
132
+ r.set(SERVER_MAC, 6); // src = our MAC
133
+ r[12] = 0x08; r[13] = 0x06;
134
+ const p = 14;
135
+ r[p] = 0; r[p + 1] = 1; r[p + 2] = 0x08; r[p + 3] = 0;
136
+ r[p + 4] = 6; r[p + 5] = 4;
137
+ r[p + 6] = 0; r[p + 7] = 2; // reply
138
+ r.set(SERVER_MAC, p + 8); // sha
139
+ r.set(SERVER_IP, p + 14); // spa
140
+ r.set(frame.subarray(p + 8, p + 14), p + 18); // tha = requester
141
+ r.set(frame.subarray(p + 14, p + 18), p + 24); // tpa
142
+ replies.push(r);
143
+ }
144
+ }
145
+ return replies;
146
+ }
147
+
148
+ if (et !== 0x0800) return replies;
149
+ const proto = frame[23];
150
+ const ihl = (frame[14] & 0x0f) * 4;
151
+ const ipStart = 14 + ihl;
152
+
153
+ if (proto === 17) { // UDP -> DHCP
154
+ const sport = (frame[ipStart] << 8) | frame[ipStart + 1];
155
+ const dport = (frame[ipStart + 2] << 8) | frame[ipStart + 3];
156
+ if (sport === 68 && dport === 67) {
157
+ const dhcp = frame.subarray(ipStart + 8);
158
+ let mt = 0;
159
+ const opt = dhcp.subarray(240);
160
+ for (let o = 0; o < opt.length;) {
161
+ if (opt[o] === 0xff) break;
162
+ if (opt[o] === 0) { o++; continue; }
163
+ if (opt[o] === 53) { mt = opt[o + 2]; break; }
164
+ o += opt[o + 1] + 2;
165
+ }
166
+ clientMac = Array.from(dhcp.subarray(28, 34));
167
+ lastMsgType = mt;
168
+ if (mt === 1) { // Discover -> Offer
169
+ stats.dhcpOffers++;
170
+ log('DHCP Discover -> Offer (XID=0x' + ((dhcp[4] << 24) | (dhcp[5] << 16) | (dhcp[6] << 8) | dhcp[7]).toString(16).padStart(8, '0') + ')');
171
+ replies.push(dhcpReply(dhcp, 2));
172
+ } else if (mt === 3) { // Request -> Ack
173
+ stats.dhcpAcks++;
174
+ log('DHCP Request -> Ack');
175
+ replies.push(dhcpReply(dhcp, 5));
176
+ }
177
+ }
178
+ return replies;
179
+ }
180
+
181
+ if (proto === 6) { // TCP
182
+ const sport = (frame[ipStart] << 8) | frame[ipStart + 1];
183
+ const dport = (frame[ipStart + 2] << 8) | frame[ipStart + 3];
184
+ if (sport !== 0 || dport !== HTTP_PORT) {
185
+ // client -> server frames; learn the ephemeral port
186
+ if (dport === HTTP_PORT) tcpSrcPort = sport;
187
+ if (tcpSrcPort === 0) return replies;
188
+ }
189
+ const seq = (frame[ipStart + 4] << 24) | (frame[ipStart + 5] << 16) | (frame[ipStart + 6] << 8) | frame[ipStart + 7];
190
+ const fl = frame[ipStart + 13];
191
+ const th = ((frame[ipStart + 12] >> 4) & 0x0f) * 4;
192
+ const dlen = frame.length - ipStart - th;
193
+
194
+ if (fl === 0x02) { // SYN
195
+ clientSeq = seq;
196
+ stats.synAcks++;
197
+ log('TCP SYN -> SYN-ACK (seq=' + seq + ')');
198
+ replies.push(tcpFrame(0x12, srvSeq, seq + 1, null));
199
+ } else if ((fl & 0x18) === 0x18 && dlen > 0) { // PSH|ACK with data (HTTP GET)
200
+ const ack = seq + dlen;
201
+ log('HTTP GET (' + dlen + 'B) -> ACK + 200 response');
202
+ replies.push(tcpFrame(0x10, srvSeq, ack, null));
203
+ replies.push(tcpFrame(0x19, srvSeq, ack, new TextEncoder().encode(HTTP_BODY))); // PSH|ACK|FIN
204
+ stats.httpResponses++;
205
+ }
206
+ return replies;
207
+ }
208
+ return replies;
209
+ }
210
+
211
+ return { onTx, stats };
212
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "stm32-periph-wasm",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "files": [
6
+ "stm32_periph_wasm_bg.wasm",
7
+ "stm32_periph_wasm.js",
8
+ "stm32_periph_wasm.d.ts"
9
+ ],
10
+ "main": "stm32_periph_wasm.js",
11
+ "types": "stm32_periph_wasm.d.ts",
12
+ "sideEffects": [
13
+ "./snippets/*"
14
+ ]
15
+ }
@@ -0,0 +1,400 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Remove a channel override, reverting it to the synthetic default.
6
+ */
7
+ export function adc_clear_channel_value(peripheral: string, channel: number): void;
8
+
9
+ /**
10
+ * Force an ADC channel's next conversion(s) to return `value` (clamped to
11
+ * 12-bit) instead of the synthetic temp/vref/vbat/random default. Unlike
12
+ * spi_tap/i2c_register_slave this can be called any time, including after
13
+ * init() — it's a global override table, not per-instance device wiring
14
+ * (see docs/components.md).
15
+ */
16
+ export function adc_set_channel_value(peripheral: string, channel: number, value: number): void;
17
+
18
+ export function add_i2c_eeprom(peripheral: string, address: number, data: Uint8Array): void;
19
+
20
+ /**
21
+ * Register a software SPI device. Must be called before init().
22
+ */
23
+ export function add_software_spi(name: string, cs: string | null | undefined, clk: string, miso: string, mosi: string): void;
24
+
25
+ /**
26
+ * Add an SPI flash device. Must be called before init().
27
+ */
28
+ export function add_spi_flash(peripheral: string, jedec_id: number, data: Uint8Array, cs?: string | null): void;
29
+
30
+ /**
31
+ * Reset the audio source and capture FIFO.
32
+ */
33
+ export function audio_clear(): void;
34
+
35
+ /**
36
+ * Load a WAV file (PCM 16-bit) as the I2S/SAI sample source. DR reads then
37
+ * consume samples from it. Returns an error string on malformed input.
38
+ */
39
+ export function audio_load_wav(bytes: Uint8Array): void;
40
+
41
+ /**
42
+ * Remaining source samples (0 when no WAV is loaded or it is exhausted).
43
+ */
44
+ export function audio_source_remaining(): number;
45
+
46
+ /**
47
+ * Drain the I2S/SAI TX capture FIFO (all DR writes since the last call).
48
+ */
49
+ export function audio_take_capture(): Uint16Array;
50
+
51
+ /**
52
+ * Forget any fed frame (stop the camera).
53
+ */
54
+ export function dcmi_clear(): void;
55
+
56
+ /**
57
+ * Provide the next camera frame to the DCMI controller (8-bit pixels,
58
+ * row-major, width x height). The next CAPTURE start consumes it.
59
+ */
60
+ export function dcmi_feed_frame(w: number, h: number, pixels: Uint8Array): void;
61
+
62
+ export function dma_get_pending(index: number): Uint32Array;
63
+
64
+ export function dma_get_pending_count(): number;
65
+
66
+ /**
67
+ * DMA peripheral-side chunked read: read `size` bytes from peripheral
68
+ * `addr` (4-byte-aligned, tail chunk partial). Replaces the JS per-chunk
69
+ * periph_read loop (one WASM call instead of size/4).
70
+ */
71
+ export function dma_periph_read(addr: number, size: number, pinc: boolean, psize: number): Uint8Array;
72
+
73
+ /**
74
+ * DMA peripheral-side chunked write: write `bytes` to peripheral `addr` in
75
+ * 4-byte chunks (tail chunk partial). Replaces the JS per-chunk periph_write
76
+ * loop (one WASM call instead of size/4).
77
+ */
78
+ export function dma_periph_write(addr: number, bytes: Uint8Array): void;
79
+
80
+ export function dma_set_completed(stream_idx: number, success: boolean): void;
81
+
82
+ /**
83
+ * Clear the RX poll flag (call after processing descriptors).
84
+ */
85
+ export function eth_clear_rx_poll(): void;
86
+
87
+ /**
88
+ * Clear the TX poll flag (call after processing descriptors).
89
+ */
90
+ export function eth_clear_tx_poll(): void;
91
+
92
+ /**
93
+ * Get the RX descriptor list address for the current poll.
94
+ */
95
+ export function eth_get_rx_desc_addr(): number;
96
+
97
+ /**
98
+ * Get the TX descriptor list address for the current poll.
99
+ */
100
+ export function eth_get_tx_desc_addr(): number;
101
+
102
+ /**
103
+ * Check if an Ethernet RX poll is pending (firmware wants to receive a packet).
104
+ */
105
+ export function eth_is_rx_poll(): boolean;
106
+
107
+ /**
108
+ * Check if an Ethernet TX poll is pending (firmware wants to send a packet).
109
+ */
110
+ export function eth_is_tx_poll(): boolean;
111
+
112
+ /**
113
+ * Signal to the peripheral that RX descriptor processing is complete.
114
+ * Call this after writing received data into RX buffers.
115
+ */
116
+ export function eth_rx_done(): void;
117
+
118
+ /**
119
+ * Re-arm the RX poll flag from JS (used when more packets are pending in gwRxQueue).
120
+ */
121
+ export function eth_signal_rx_poll(desc_addr: number): void;
122
+
123
+ /**
124
+ * Re-arm the TX poll flag from JS (used when more TX descriptors are pending).
125
+ */
126
+ export function eth_signal_tx_poll(desc_addr: number): void;
127
+
128
+ /**
129
+ * Signal to the peripheral that TX descriptor processing is complete.
130
+ * Call this after walking TX descriptors and sending the packet.
131
+ */
132
+ export function eth_tx_done(): void;
133
+
134
+ /**
135
+ * Called by the JS driver after it applied the queued erase to guest memory;
136
+ * clears BSY/EOP so the firmware's busy-wait can proceed.
137
+ */
138
+ export function flash_erase_applied(): void;
139
+
140
+ /**
141
+ * True when the FLASH peripheral is unlocked with PG set and !BSY — the
142
+ * JS driver applies program writes to guest memory when this is true.
143
+ */
144
+ export function flash_is_programming(): boolean;
145
+
146
+ /**
147
+ * Consume a completed erase request (start, len) the JS driver must apply
148
+ * to guest memory (all bytes 0xFF). Empty vec = nothing pending.
149
+ */
150
+ export function flash_take_erase(): Uint32Array;
151
+
152
+ /**
153
+ * Queue values the JS device answers on subsequent bank reads, oldest
154
+ * first. An exhausted queue reads back 0.
155
+ */
156
+ export function fsmc_push_data(bank: number, values: Uint32Array): void;
157
+
158
+ /**
159
+ * Drain all FSMC tap events for a bank since the last call (2 words per
160
+ * access, see `fsmc_tap`).
161
+ */
162
+ export function fsmc_take_events(bank: number): Uint32Array;
163
+
164
+ /**
165
+ * Register a protocol-agnostic tap on an FSMC memory bank (0 = BANK1, the
166
+ * 0x6000_0000 window). Must be called before init(): the Fsmc peripheral
167
+ * binds its banks' devices once at construction and never rescans.
168
+ *
169
+ * Every data-space access to the bank is queued for JS as TWO words —
170
+ * header then value — where the header is `1<<31 | offset` for a write and
171
+ * `offset` for a read. The offset matters: memory-mapped displays in
172
+ * 8080 mode decode an address line as RS/DC, so the address is the only
173
+ * thing separating a command write from a pixel write.
174
+ */
175
+ export function fsmc_tap(bank: number): void;
176
+
177
+ export function get_next_pending_interrupt(): number;
178
+
179
+ /**
180
+ * Collect UART output since last call.
181
+ */
182
+ export function get_uart_output(): string;
183
+
184
+ export function gpio_read_input(port: number, pin: number): boolean;
185
+
186
+ export function gpio_read_output(port: number, pin: number): boolean;
187
+
188
+ export function gpio_set_input(port: number, pin: number, value: boolean): void;
189
+
190
+ /**
191
+ * Check if any interrupt is pending (non-consuming).
192
+ */
193
+ export function has_pending_interrupt(): boolean;
194
+
195
+ /**
196
+ * Queue bytes the tapped I2C slave answers on master reads.
197
+ */
198
+ export function i2c_push_rx(peripheral: string, bytes: Uint8Array): void;
199
+
200
+ /**
201
+ * Read one register of the first matching regfile on a peripheral.
202
+ */
203
+ export function i2c_regfile_get(peripheral: string, offset: number): number;
204
+
205
+ /**
206
+ * Write one register of the first matching regfile on a peripheral
207
+ * (JS-side poke, e.g. temperature coming from outside the guest).
208
+ */
209
+ export function i2c_regfile_set(peripheral: string, offset: number, value: number): void;
210
+
211
+ /**
212
+ * Register a pointer-addressed register file (DS3231 RTC style) on an I2C
213
+ * peripheral. Must be called before init(). The first write byte of each
214
+ * transaction is the register pointer, subsequent bytes land at `ptr++`;
215
+ * reads return `regs[ptr++]` (pointer persists across address matches).
216
+ */
217
+ export function i2c_register_regfile(peripheral: string, address: number, size: number, init: Uint8Array): void;
218
+
219
+ /**
220
+ * Register a protocol-agnostic I2C slave on a peripheral. Must be called
221
+ * before init(). The address is ACKed like any other registered slave;
222
+ * master writes queue for JS (`i2c_take_tx`) and JS-pushed bytes are
223
+ * returned on master reads (`i2c_push_rx`).
224
+ */
225
+ export function i2c_register_slave(peripheral: string, address: number): void;
226
+
227
+ /**
228
+ * Drain all events for a tapped I2C slave since the last call. Each entry
229
+ * is a u32: bit31 = START/STOP boundary event (bit30 = 1 START / 0 STOP),
230
+ * otherwise the low byte is one byte the master wrote to the slave.
231
+ */
232
+ export function i2c_take_events(peripheral: string): Uint32Array;
233
+
234
+ /**
235
+ * Initialize the emulator with hardcoded peripheral map.
236
+ * Must be called after adding all ext devices (add_spi_flash, add_i2c_eeprom).
237
+ */
238
+ export function init(): void;
239
+
240
+ /**
241
+ * Initialize the emulator from an SVD XML string (e.g., STM32F407.svd).
242
+ * Must be called after adding all ext devices (add_spi_flash, add_i2c_eeprom).
243
+ */
244
+ export function init_svd(svd_xml: string): void;
245
+
246
+ export function is_watchdog_reset_requested(): boolean;
247
+
248
+ /**
249
+ * Frames completed by the LTDC scanout since enable.
250
+ */
251
+ export function ltdc_get_frame_count(): number;
252
+
253
+ /**
254
+ * Current LTDC scanline (0xFFFF when the controller is disabled).
255
+ */
256
+ export function ltdc_get_scanline(): number;
257
+
258
+ export function periph_read(addr: number, width: number): number;
259
+
260
+ export function periph_write(addr: number, width: number, value: number): void;
261
+
262
+ /**
263
+ * Clear all process-lifetime globals so a NEW emulator instance starts
264
+ * clean. Must be called before registering that instance's devices.
265
+ * Without it, `ExtDevices` accumulates and a second instance silently binds
266
+ * to the FIRST instance's devices (see system::reset_globals).
267
+ */
268
+ export function reset_state(): void;
269
+
270
+ /**
271
+ * Debug: flash state summary [wel, status1, cs_state, dummy_pending, pending_program_len]
272
+ */
273
+ export function spi_flash_debug(peripheral: string): Uint32Array;
274
+
275
+ /**
276
+ * Push bytes the JS device answers on the MISO line (read transactions).
277
+ */
278
+ export function spi_push_miso(peripheral: string, bytes: Uint8Array): void;
279
+
280
+ /**
281
+ * Drain all SPI tap events for a peripheral since the last call.
282
+ */
283
+ export function spi_take_events(peripheral: string): Uint32Array;
284
+
285
+ /**
286
+ * Register a protocol-agnostic tap on an SPI peripheral. Must be called
287
+ * before init(). `cs` optionally names the GPIO pin used as chip select
288
+ * ("PA4"); when given, CS edges are reported in the event stream. `dc`
289
+ * optionally names a data/command pin; its level is reported in bit 29 of
290
+ * each byte event (1 = data) so the JS device can parse TFT-style traffic.
291
+ */
292
+ export function spi_tap(peripheral: string, cs?: string | null, dc?: string | null): void;
293
+
294
+ export function tick(): void;
295
+
296
+ /**
297
+ * Same as tick() but accounts for `delta` instructions at once. Timer
298
+ * peripherals are instruction-count driven, so batching ticks with a
299
+ * delta is semantically identical to one tick per instruction.
300
+ */
301
+ export function tick_n(delta: number): void;
302
+
303
+ /**
304
+ * Inject a received byte into the UART at the given peripheral base address.
305
+ * Returns true if a peripheral was found at that address.
306
+ */
307
+ export function uart_rx_byte(addr: number, byte: number): boolean;
308
+
309
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
310
+
311
+ export interface InitOutput {
312
+ readonly memory: WebAssembly.Memory;
313
+ readonly adc_clear_channel_value: (a: number, b: number, c: number) => void;
314
+ readonly adc_set_channel_value: (a: number, b: number, c: number, d: number) => void;
315
+ readonly add_i2c_eeprom: (a: number, b: number, c: number, d: number, e: number) => void;
316
+ readonly add_software_spi: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void;
317
+ readonly add_spi_flash: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
318
+ readonly audio_clear: () => void;
319
+ readonly audio_load_wav: (a: number, b: number) => [number, number];
320
+ readonly audio_source_remaining: () => number;
321
+ readonly audio_take_capture: () => [number, number];
322
+ readonly dcmi_clear: () => void;
323
+ readonly dcmi_feed_frame: (a: number, b: number, c: number, d: number) => void;
324
+ readonly dma_get_pending: (a: number) => [number, number];
325
+ readonly dma_get_pending_count: () => number;
326
+ readonly dma_periph_read: (a: number, b: number, c: number, d: number) => [number, number];
327
+ readonly dma_periph_write: (a: number, b: number, c: number) => void;
328
+ readonly dma_set_completed: (a: number, b: number) => void;
329
+ readonly eth_clear_rx_poll: () => void;
330
+ readonly eth_clear_tx_poll: () => void;
331
+ readonly eth_get_rx_desc_addr: () => number;
332
+ readonly eth_get_tx_desc_addr: () => number;
333
+ readonly eth_is_rx_poll: () => number;
334
+ readonly eth_is_tx_poll: () => number;
335
+ readonly eth_rx_done: () => void;
336
+ readonly eth_signal_rx_poll: (a: number) => void;
337
+ readonly eth_signal_tx_poll: (a: number) => void;
338
+ readonly eth_tx_done: () => void;
339
+ readonly flash_erase_applied: () => void;
340
+ readonly flash_is_programming: () => number;
341
+ readonly flash_take_erase: () => [number, number];
342
+ readonly fsmc_push_data: (a: number, b: number, c: number) => void;
343
+ readonly fsmc_take_events: (a: number) => [number, number];
344
+ readonly fsmc_tap: (a: number) => void;
345
+ readonly get_next_pending_interrupt: () => number;
346
+ readonly get_uart_output: () => [number, number];
347
+ readonly gpio_read_input: (a: number, b: number) => number;
348
+ readonly gpio_read_output: (a: number, b: number) => number;
349
+ readonly gpio_set_input: (a: number, b: number, c: number) => void;
350
+ readonly has_pending_interrupt: () => number;
351
+ readonly i2c_push_rx: (a: number, b: number, c: number, d: number) => void;
352
+ readonly i2c_regfile_get: (a: number, b: number, c: number) => number;
353
+ readonly i2c_regfile_set: (a: number, b: number, c: number, d: number) => void;
354
+ readonly i2c_register_regfile: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
355
+ readonly i2c_register_slave: (a: number, b: number, c: number) => void;
356
+ readonly i2c_take_events: (a: number, b: number) => [number, number];
357
+ readonly init: () => void;
358
+ readonly init_svd: (a: number, b: number) => void;
359
+ readonly is_watchdog_reset_requested: () => number;
360
+ readonly ltdc_get_frame_count: () => number;
361
+ readonly ltdc_get_scanline: () => number;
362
+ readonly periph_read: (a: number, b: number) => number;
363
+ readonly periph_write: (a: number, b: number, c: number) => void;
364
+ readonly reset_state: () => void;
365
+ readonly spi_flash_debug: (a: number, b: number) => [number, number];
366
+ readonly spi_push_miso: (a: number, b: number, c: number, d: number) => void;
367
+ readonly spi_take_events: (a: number, b: number) => [number, number];
368
+ readonly spi_tap: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
369
+ readonly tick: () => void;
370
+ readonly tick_n: (a: number) => void;
371
+ readonly uart_rx_byte: (a: number, b: number) => number;
372
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
373
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
374
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
375
+ readonly __wbindgen_externrefs: WebAssembly.Table;
376
+ readonly __externref_table_dealloc: (a: number) => void;
377
+ readonly __wbindgen_start: () => void;
378
+ }
379
+
380
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
381
+
382
+ /**
383
+ * Instantiates the given `module`, which can either be bytes or
384
+ * a precompiled `WebAssembly.Module`.
385
+ *
386
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
387
+ *
388
+ * @returns {InitOutput}
389
+ */
390
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
391
+
392
+ /**
393
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
394
+ * for everything else, calls `WebAssembly.instantiate` directly.
395
+ *
396
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
397
+ *
398
+ * @returns {Promise<InitOutput>}
399
+ */
400
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;