diff --git a/README.md b/README.md index d073c15..1ec555e 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,9 @@ unoccupied byte between the tail and the head. | Name | Address | Size / B | Access | |----------|---------|----------|--------------| | SYSREADY | 110h | 4 | atomic write | +| SYSINTER | 114h | 4 | atomic read | The `SYSREADY` register is used to indicate when the system has booted -up and is ready for user input. +up and is ready for user input. `SYSINTER` is set (and notified on) +once the emulator has enabled user input and the system is +interactive. diff --git a/emu.js b/emu.js index 86d6c40..c9943d4 100644 --- a/emu.js +++ b/emu.js @@ -6,6 +6,7 @@ const RXHEAD = 0x108; const RXTAIL = 0x10c; const SYSREADY = 0x110; +const SYSINTER = 0x114; const DOT_INTERVAL_MS = 120; const PERIPHS_SIZE = 0x200; @@ -50,14 +51,18 @@ class Emulator { document.addEventListener('keydown', (e) => this.handle_keydown(e)); window.addEventListener('resize', () => this.handle_resize()); + this.forth = new Worker('boot.js', { type: 'module' }); + this.print("Assembling kernel "); - const dots = setInterval(() => this.print("."), DOT_INTERVAL_MS); - this.worker = new Worker('boot.js', { type: 'module' }); - this.worker.postMessage({ type: "load", mem: this.mem }); - this.worker.onmessage = (e) => { - clearInterval(dots); + this.dots = setInterval(() => this.print("."), DOT_INTERVAL_MS); + this.forth.postMessage({ type: "load", mem: this.mem }); + this.forth.onmessage = (e) => { + clearInterval(this.dots); this.print(" done\n"); - this.worker.postMessage({ type: "boot" }); + + this.print("Loading prelude "); + this.forth.postMessage({ type: "boot" }); + this.dots = setInterval(() => this.print("."), DOT_INTERVAL_MS); }; fetch('prelude.f') @@ -84,9 +89,15 @@ class Emulator { if (!this.input_enable) { const sysready = Atomics.load(this.mem_u8, SYSREADY); if (sysready != 0) { + clearInterval(this.dots); + this.print(" done\n"); + + Atomics.store(this.mem_u8, SYSINTER, 1); + Atomics.notify(this.mem_i32, SYSINTER / 4); + this.input_enable = true; + this.blink = true; this.flush_output(); - document.getElementById('cursor').classList.add('blinking'); } } } @@ -180,12 +191,14 @@ class Emulator { } e.preventDefault(); + this.blink = false; this.flush_output(); document.getElementById('cursor').classList.remove('blinking'); if (this.idle_timer) clearTimeout(this.idle_timer); this.idle_timer = setTimeout(() => { + this.blink = true; document.getElementById('cursor').classList.add('blinking'); }, CURSOR_IDLE_TIME_MS); } @@ -272,10 +285,12 @@ class Emulator { return row.map((c, x) => { const ec = this.html_escape(c); if (this.input_enable - && x == this.cursor.x && y == this.cursor.y) - return '' + ec + ''; - else + && x == this.cursor.x && y == this.cursor.y) { + const cl = this.blink ? 'class="blinking"' : ''; + return `` + ec + ''; + } else { return ec; + } }).join('').trimEnd(); }).join('\n'); this.output.innerHTML = html; diff --git a/prelude.f b/prelude.f index 4c7e2d4..16b1236 100644 --- a/prelude.f +++ b/prelude.f @@ -1,12 +1,5 @@ -76 EMIT 111 EMIT 97 EMIT 100 EMIT 105 EMIT 110 EMIT 103 EMIT 32 EMIT -112 EMIT 114 EMIT 101 EMIT 108 EMIT 117 EMIT 100 EMIT 101 EMIT 32 EMIT - : \ KEY 10 = 0BRANCH [ -20 , ] ; IMMEDIATE \ Now we have line comments :) -\ We'll periodically sprinkle these in so that it's clear to the user -\ that things are happening. -46 EMIT - \ Conditionals : IF @@ -27,8 +20,6 @@ SWAP ! ; IMMEDIATE -46 EMIT - \ Loops : BEGIN HERE @ ; IMMEDIATE @@ -43,8 +34,6 @@ HERE @ - , ; IMMEDIATE -46 EMIT - \ Recursive calls : RECURSE LATEST @ >CFA , ; IMMEDIATE @@ -61,8 +50,6 @@ ( ( Take that, C ) ) -46 EMIT - \ Printing utilities : CR 10 EMIT ; @@ -80,8 +67,6 @@ + EMIT ; -CHAR . EMIT - : . \ Handle negatives DUP 0< IF CHAR - EMIT NEGATE THEN @@ -110,8 +95,6 @@ CHAR . EMIT 2DROP ; -CHAR . EMIT - : TYPE ( addr len -- ) BEGIN DUP 0= IF 2DROP EXIT THEN @@ -120,8 +103,6 @@ CHAR . EMIT AGAIN ; -CHAR . EMIT - : C, HERE @ C! 1 HERE +! ; : ." @@ -151,8 +132,6 @@ CHAR . EMIT THEN ; IMMEDIATE -CHAR . EMIT - \ Misc utilities : NIP SWAP DROP ; @@ -171,8 +150,6 @@ CHAR . EMIT : [COMPILE] ' , ; IMMEDIATE -CHAR . EMIT - \ Constants, variables and values : CONSTANT @@ -204,8 +181,6 @@ CHAR . EMIT THEN ; IMMEDIATE -CHAR . EMIT - \ Peripheral register addresses HEX @@ -217,11 +192,10 @@ HEX 108 CONSTANT RXHEAD 10C CONSTANT RXTAIL 110 CONSTANT SYSREADY +114 CONSTANT SYSINTER DECIMAL -46 EMIT - \ A better word-not-found handler : ANY-RX? RXHEAD AC@ RXTAIL AC@ <> ; @@ -244,8 +218,6 @@ DECIMAL ' WNF-HANDLER TO WNFHOOK -CHAR . EMIT - \ Version number 0 CONSTANT VERSION-MAJOR @@ -258,8 +230,6 @@ CHAR . EMIT CHAR . EMIT VERSION-PATCH . ; -CHAR . EMIT - \ Welcome banner : BANNER @@ -277,8 +247,8 @@ CHAR . EMIT CR ; -." done" CR -BANNER - -\ Set SYSREADY high to enable user input +\ Set SYSREADY high and wait until interactive 1 SYSREADY AC! +SYSINTER WAIT DROP + +BANNER diff --git a/wipforth.ws b/wipforth.ws index a0cd37a..5deb1e9 100644 --- a/wipforth.ws +++ b/wipforth.ws @@ -635,6 +635,15 @@ end call next +.func wait +.elem codewords wait WAIT_CODEWORD + call pop + i32.const 0 + i64.const -1 + memory.atomic.wait32 2 0 + call push + call next + ;; Core utility words .func exit @@ -1226,6 +1235,15 @@ COPY: .word COPY_CODEWORD .def PREV _COPY +_WAIT: + .word PREV + .byte 4 + .utf8 "WAIT" + .align +WAIT: + .word WAIT_CODEWORD +.def PREV _WAIT + _EXIT: .word PREV .byte 4