Rejig serial periph

This commit is contained in:
2026-02-24 15:53:43 +00:00
parent 0608e2c476
commit d11805cd6c
2 changed files with 23 additions and 34 deletions

View File

@@ -30,20 +30,19 @@ these headers.
|--------|--------|----------|--------------| |--------|--------|----------|--------------|
| TXBUF | 0 | 32 | write | | TXBUF | 0 | 32 | write |
| RXBUF | 32 | 32 | read | | RXBUF | 32 | 32 | read |
| TXDATA | 64 | 1 | atomic write | | TXHEAD | 64 | 1 | atomic read |
| TXHEAD | 65 | 1 | atomic read | | TXTAIL | 65 | 1 | atomic write |
| TXTAIL | 66 | 1 | atomic write | | RXHEAD | 66 | 1 | atomic write |
| RXDATA | 67 | 1 | atomic read | | RXTAIL | 67 | 1 | atomic read |
| RXHEAD | 68 | 1 | atomic write |
| RXTAIL | 69 | 1 | atomic read |
For both sending (`TX`) and receiving (`RX`), there are four For both sending (`TX`) and receiving (`RX`), there are three
registers: `xBUF`, `xDATA`, `xHEAD` and `xTAIL`: registers: `xBUF`, `xHEAD` and `xTAIL`:
- `xBUF` registers are 32-byte FIFO ring buffers used for data - `xBUF` registers are 32-byte FIFO ring buffers used for data
- The `xDATA` registers indicate whether data is available (0 for - The `xHEAD` and `xTAIL` registers specify the start and end of data
data, FFh for no data) in the ring buffer, `xHEAD` being the offset of the first byte of
- The `xHEAD` and `xTAIL` registers specify the start and end of data, and `xTAIL` being the offset of the first byte *after* the data.
data in the FIFO, `xHEAD` being the offset of the first byte of
data, and `xTAIL` being the offset of the first byte after the In order to be distinguishable from the empty state, the ring buffers
data. must never be completely full -- there must always be *at least one*
unoccupied byte between the tail and the head.

30
emu.js
View File

@@ -1,15 +1,13 @@
const TXBUF = 0; const TXBUF = 0;
const RXBUF = 32; const RXBUF = 32;
const TXDATA = 64; const TXHEAD = 64;
const TXHEAD = 65; const TXTAIL = 65;
const TXTAIL = 66; const RXHEAD = 66;
const RXDATA = 67; const RXTAIL = 67;
const RXHEAD = 68;
const RXTAIL = 69;
const TXBUF_SIZE = 32; const TXBUF_SIZE = 32;
const RXBUF_SIZE = 32; const RXBUF_SIZE = 32;
const PERIPHS_SIZE = 70; const PERIPHS_SIZE = 68;
const POLL_INTERVAL_MS = 20; const POLL_INTERVAL_MS = 20;
@@ -36,29 +34,21 @@ class Emulator {
} }
poll() { poll() {
const txdata = Atomics.load(this.mem_u8, TXDATA); const txhead = Atomics.load(this.mem_u8, TXHEAD);
if (txdata !== 0) const txtail = Atomics.load(this.mem_u8, TXTAIL);
this.handle_txdata(); if (txhead !== txtail)
this.handle_txdata(txhead, txtail);
} }
handle_txdata() { handle_txdata(head, tail) {
const head = Atomics.load(this.mem_u8, TXHEAD);
const tail = Atomics.load(this.mem_u8, TXTAIL);
const data = []; const data = [];
let i = head; let i = head;
do { do {
data.push(this.mem_u8[TXBUF + i]); data.push(this.mem_u8[TXBUF + i]);
i = (i + 1) % TXBUF_SIZE; i = (i + 1) % TXBUF_SIZE;
} while (i !== tail); } while (i !== tail);
Atomics.store(this.mem_u8, TXHEAD, tail); Atomics.store(this.mem_u8, TXHEAD, tail);
// More data could have been added -- only clear TXDATA if
// tail is unchanged.
if (tail === Atomics.load(this.mem_u8, TXTAIL))
Atomics.store(this.mem_u8, TXDATA, 0);
const str = this.decoder.decode(new Uint8Array(data)); const str = this.decoder.decode(new Uint8Array(data));
this.output.innerText += str; this.output.innerText += str;
} }