Skip to content

Commit 526759c

Browse files
Typecheck jshal.js.
It's most practical for it to remain JS as it's splatted into the Emscripten build but it's too easy to break right now. Fixes radio receive.
1 parent 4d83adb commit 526759c

File tree

3 files changed

+128
-36
lines changed

3 files changed

+128
-36
lines changed

src/board/index.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ export class Board {
8787
* Defined during start().
8888
*/
8989
private modulePromise: Promise<ModuleWrapper> | undefined;
90+
/**
91+
* Defined by start but async.
92+
*/
93+
private module: ModuleWrapper | undefined;
9094
/**
9195
* If undefined, then when main finishes we stay stopped.
9296
* Otherwise we perform the action then clear this field.
@@ -316,12 +320,13 @@ export class Board {
316320
}
317321

318322
private async start() {
319-
if (this.modulePromise) {
323+
if (this.modulePromise || this.module) {
320324
throw new Error("Module already exists!");
321325
}
322326

323327
this.modulePromise = this.createModule();
324328
const module = await this.modulePromise;
329+
this.module = module;
325330
let panicCode: number | undefined;
326331
try {
327332
this.displayRunningState();
@@ -346,6 +351,7 @@ export class Board {
346351
// Called by the HAL for normal shutdown but not in error scenarios.
347352
this.stopComponents();
348353
this.modulePromise = undefined;
354+
this.module = undefined;
349355

350356
if (panicCode !== undefined) {
351357
this.displayPanic(panicCode);
@@ -371,9 +377,11 @@ export class Board {
371377
this.displayStoppedState();
372378
}
373379
if (this.modulePromise) {
380+
// Avoid this.module as we might still be creating it (async).
374381
const module = await this.modulePromise;
375382
module.requestStop();
376383
this.modulePromise = undefined;
384+
this.module = undefined;
377385
// Ctrl-C, Ctrl-D to interrupt the main loop.
378386
this.writeSerialInput("\x03\x04");
379387
}
@@ -543,6 +551,13 @@ export class Board {
543551
}
544552
}
545553

554+
writeRadioRxBuffer(packet: Uint8Array): void {
555+
if (!this.module) {
556+
throw new Error("Must be running");
557+
}
558+
this.module.writeRadioRxBuffer(packet);
559+
}
560+
546561
initialize() {
547562
this.epoch = new Date().getTime();
548563
this.serialInputBuffer.length = 0;

src/jshal.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { EmscriptenModule } from "./board/wasm";
2+
3+
global {
4+
// In reality this is a local variable as jshal.js is splatted into the generated code.
5+
declare const Module: EmscriptenModule;
6+
declare const LibraryManager: {
7+
library: any;
8+
};
9+
10+
// Just what we need. There are lots more Emscripten helpers available.
11+
declare function UTF8ToString(ptr: number, len?: number);
12+
declare function stringToUTF8(s: string, buf: number, len: number);
13+
declare function lengthBytesUTF8(s: string);
14+
declare function mergeInto(library: any, functions: Record<string, function>);
15+
}

src/jshal.js

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
// @ts-check
28+
/// <reference path="./jshal.d.ts" />
29+
2730
mergeInto(LibraryManager.library, {
2831
mp_js_hal_init: async function () {
2932
Module.board.initialize();
@@ -41,20 +44,32 @@ mergeInto(LibraryManager.library, {
4144
return Module.board.readSerialInput();
4245
},
4346

44-
mp_js_hal_stdout_tx_strn: function (ptr, len) {
47+
mp_js_hal_stdout_tx_strn: function (
48+
/** @type {number} */ ptr,
49+
/** @type {number} */ len
50+
) {
4551
Module.board.writeSerialOutput(UTF8ToString(ptr, len));
4652
},
4753

48-
mp_js_hal_filesystem_find: function (name, len) {
54+
mp_js_hal_filesystem_find: function (
55+
/** @type {number} */ name,
56+
/** @type {number} */ len
57+
) {
4958
return Module.fs.find(UTF8ToString(name, len));
5059
},
5160

52-
mp_js_hal_filesystem_create: function (name, len) {
61+
mp_js_hal_filesystem_create: function (
62+
/** @type {number} */ name,
63+
/** @type {number} */ len
64+
) {
5365
const filename = UTF8ToString(name, len);
5466
return Module.fs.create(filename);
5567
},
5668

57-
mp_js_hal_filesystem_name: function (idx, buf) {
69+
mp_js_hal_filesystem_name: function (
70+
/** @type {number} */ idx,
71+
/** @type {number} */ buf
72+
) {
5873
const name = Module.fs.name(idx);
5974
if (name === undefined) {
6075
return -1;
@@ -64,52 +79,66 @@ mergeInto(LibraryManager.library, {
6479
return len;
6580
},
6681

67-
mp_js_hal_filesystem_size: function (idx) {
82+
mp_js_hal_filesystem_size: function (/** @type {number} */ idx) {
6883
return Module.fs.size(idx);
6984
},
7085

71-
mp_js_hal_filesystem_remove: function (idx) {
86+
mp_js_hal_filesystem_remove: function (/** @type {number} */ idx) {
7287
return Module.fs.remove(idx);
7388
},
7489

75-
mp_js_hal_filesystem_readbyte: function (idx, offset) {
90+
mp_js_hal_filesystem_readbyte: function (
91+
/** @type {number} */ idx,
92+
/** @type {number} */ offset
93+
) {
7694
return Module.fs.readbyte(idx, offset);
7795
},
7896

79-
mp_js_hal_filesystem_write: function (idx, buf, len) {
80-
const data = new Uint8Array(HEAP8.buffer, buf, len);
97+
mp_js_hal_filesystem_write: function (
98+
/** @type {number} */ idx,
99+
/** @type {number} */ buf,
100+
/** @type {number} */ len
101+
) {
102+
const data = new Uint8Array(Module.HEAPU8.buffer, buf, len);
81103
return Module.fs.write(idx, data);
82104
},
83105

84106
mp_js_hal_reset: function () {
85107
Module.board.throwReset();
86108
},
87109

88-
mp_js_hal_panic: function (code) {
110+
mp_js_hal_panic: function (/** @type {number} */ code) {
89111
Module.board.throwPanic(code);
90112
},
91113

92114
mp_js_hal_temperature: function () {
93115
return Module.board.temperature.value;
94116
},
95117

96-
mp_js_hal_button_get_presses: function (button) {
118+
mp_js_hal_button_get_presses: function (/** @type {number} */ button) {
97119
return Module.board.buttons[button].getAndClearPresses();
98120
},
99121

100-
mp_js_hal_button_is_pressed: function (button) {
122+
mp_js_hal_button_is_pressed: function (/** @type {number} */ button) {
101123
return Module.board.buttons[button].isPressed();
102124
},
103125

104-
mp_js_hal_pin_is_touched: function (pin) {
126+
mp_js_hal_pin_is_touched: function (/** @type {number} */ pin) {
105127
return Module.board.pins[pin].isTouched();
106128
},
107129

108-
mp_js_hal_display_get_pixel: function (x, y) {
130+
mp_js_hal_display_get_pixel: function (
131+
/** @type {number} */ x,
132+
/** @type {number} */ y
133+
) {
109134
return Module.board.display.getPixel(x, y);
110135
},
111136

112-
mp_js_hal_display_set_pixel: function (x, y, value) {
137+
mp_js_hal_display_set_pixel: function (
138+
/** @type {number} */ x,
139+
/** @type {number} */ y,
140+
/** @type {number} */ value
141+
) {
113142
Module.board.display.setPixel(x, y, value);
114143
},
115144

@@ -139,7 +168,7 @@ mergeInto(LibraryManager.library, {
139168
);
140169
},
141170

142-
mp_js_hal_accelerometer_set_range: function (r) {
171+
mp_js_hal_accelerometer_set_range: function (/** @type {number} */ r) {
143172
Module.board.accelerometer.setRange(r);
144173
},
145174

@@ -163,51 +192,68 @@ mergeInto(LibraryManager.library, {
163192
return Module.board.compass.state.compassHeading.value;
164193
},
165194

166-
mp_js_hal_audio_set_volume: function (value) {
195+
mp_js_hal_audio_set_volume: function (/** @type {number} */ value) {
167196
Module.board.audio.setVolume(value);
168197
},
169198

170-
mp_js_hal_audio_init: function (sample_rate) {
199+
mp_js_hal_audio_init: function (/** @type {number} */ sample_rate) {
200+
// @ts-expect-error
171201
Module.board.audio.default.init(sample_rate);
172202
},
173203

174-
mp_js_hal_audio_write_data: function (buf, num_samples) {
204+
mp_js_hal_audio_write_data: function (
205+
/** @type {number} */ buf,
206+
/** @type {number} */ num_samples
207+
) {
208+
// @ts-expect-error
175209
Module.board.audio.default.writeData(
176210
Module.conversions.convertAudioBuffer(
177211
Module.HEAPU8,
178212
buf,
213+
// @ts-expect-error
179214
Module.board.audio.default.createBuffer(num_samples)
180215
)
181216
);
182217
},
183218

184-
mp_js_hal_audio_speech_init: function (sample_rate) {
219+
mp_js_hal_audio_speech_init: function (/** @type {number} */ sample_rate) {
220+
// @ts-expect-error
185221
Module.board.audio.speech.init(sample_rate);
186222
},
187223

188-
mp_js_hal_audio_speech_write_data: function (buf, num_samples) {
224+
mp_js_hal_audio_speech_write_data: function (
225+
/** @type {number} */ buf,
226+
/** @type {number} */ num_samples
227+
) {
228+
// @ts-expect-error
189229
Module.board.audio.speech.writeData(
190230
Module.conversions.convertAudioBuffer(
191231
Module.HEAPU8,
192232
buf,
233+
// @ts-expect-error
193234
Module.board.audio.speech.createBuffer(num_samples)
194235
)
195236
);
196237
},
197238

198-
mp_js_hal_audio_period_us: function (period_us) {
239+
mp_js_hal_audio_period_us: function (/** @type {number} */ period_us) {
199240
Module.board.audio.setPeriodUs(period_us);
200241
},
201242

202-
mp_js_hal_audio_amplitude_u10: function (amplitude_u10) {
243+
mp_js_hal_audio_amplitude_u10: function (
244+
/** @type {number} */ amplitude_u10
245+
) {
203246
Module.board.audio.setAmplitudeU10(amplitude_u10);
204247
},
205248

206249
mp_js_hal_microphone_init: function () {
207250
Module.board.microphone.microphoneOn();
208251
},
209252

210-
mp_js_hal_microphone_set_threshold: function (kind, value) {
253+
mp_js_hal_microphone_set_threshold: function (
254+
/** @type {number} */ kind,
255+
/** @type {number} */ value
256+
) {
211257
Module.board.microphone.setThreshold(
212258
Module.conversions.convertSoundThresholdNumberToString(kind),
213259
value
@@ -218,7 +264,7 @@ mergeInto(LibraryManager.library, {
218264
return Module.board.microphone.soundLevel.value;
219265
},
220266

221-
mp_js_hal_audio_play_expression: function (expr) {
267+
mp_js_hal_audio_play_expression: function (/** @type {any} */ expr) {
222268
return Module.board.audio.playSoundExpression(UTF8ToString(expr));
223269
},
224270

@@ -230,29 +276,42 @@ mergeInto(LibraryManager.library, {
230276
return Module.board.audio.isSoundExpressionActive();
231277
},
232278

233-
mp_js_radio_enable: function (group, max_payload, queue) {
279+
mp_js_radio_enable: function (
280+
/** @type {number} */ group,
281+
/** @type {number} */ max_payload,
282+
/** @type {number} */ queue
283+
) {
234284
Module.board.radio.enable({ group, maxPayload: max_payload, queue });
235285
},
236286

237287
mp_js_radio_disable: function () {
238288
Module.board.radio.disable();
239289
},
240290

241-
mp_js_radio_update_config: function (group, max_payload, queue) {
291+
mp_js_radio_update_config: function (
292+
/** @type {number} */ group,
293+
/** @type {number} */ max_payload,
294+
/** @type {number} */ queue
295+
) {
242296
Module.board.radio.updateConfig({ group, maxPayload: max_payload, queue });
243297
},
244298

245-
mp_js_radio_send: function (buf, len, buf2, len2) {
299+
mp_js_radio_send: function (
300+
/** @type {number} */ buf,
301+
/** @type {number} */ len,
302+
/** @type {number} */ buf2,
303+
/** @type {number} */ len2
304+
) {
246305
const data = new Uint8Array(len + len2);
247-
data.set(HEAPU8.slice(buf, buf + len));
248-
data.set(HEAPU8.slice(buf2, buf2 + len2), len);
306+
data.set(Module.HEAPU8.slice(buf, buf + len));
307+
data.set(Module.HEAPU8.slice(buf2, buf2 + len2), len);
249308
Module.board.radio.send(data);
250309
},
251310

252311
mp_js_radio_peek: function () {
253312
const packet = Module.board.radio.peek();
254313
if (packet) {
255-
return Module.board.module.writeRadioRxBuffer(packet);
314+
return Module.board.writeRadioRxBuffer(packet);
256315
}
257316
return null;
258317
},
@@ -261,16 +320,16 @@ mergeInto(LibraryManager.library, {
261320
Module.board.radio.pop();
262321
},
263322

264-
mp_js_hal_log_delete: function (full_erase) {
323+
mp_js_hal_log_delete: function (/** @type {boolean} */ full_erase) {
265324
// We don't have a notion of non-full erase.
266325
Module.board.dataLogging.delete();
267326
},
268327

269-
mp_js_hal_log_set_mirroring: function (serial) {
328+
mp_js_hal_log_set_mirroring: function (/** @type {boolean} */ serial) {
270329
Module.board.dataLogging.setMirroring(serial);
271330
},
272331

273-
mp_js_hal_log_set_timestamp: function (period) {
332+
mp_js_hal_log_set_timestamp: function (/** @type {number} */ period) {
274333
Module.board.dataLogging.setTimestamp(period);
275334
},
276335

@@ -282,7 +341,10 @@ mergeInto(LibraryManager.library, {
282341
return Module.board.dataLogging.endRow();
283342
},
284343

285-
mp_js_hal_log_data: function (key, value) {
344+
mp_js_hal_log_data: function (
345+
/** @type {number} */ key,
346+
/** @type {number} */ value
347+
) {
286348
return Module.board.dataLogging.logData(
287349
UTF8ToString(key),
288350
UTF8ToString(value)

0 commit comments

Comments
 (0)