update plan after kernal module reseach
This commit is contained in:
parent
d7a9b94e0a
commit
e5e51754b2
@ -62,11 +62,14 @@ From the research, a pure listener has a radically reduced surface:
|
|||||||
|-------|-------------------------|--------------|
|
|-------|-------------------------|--------------|
|
||||||
| ATN | C64 drives; we react | **input** |
|
| ATN | C64 drives; we react | **input** |
|
||||||
| CLK | Talker (C64) drives during data; we sample | **input** |
|
| CLK | Talker (C64) drives during data; we sample | **input** |
|
||||||
| DATA | Listener drives (ack ATN, ready, byte-ack, EOI-ack) | **output** (open-collector) |
|
| DATA | Listener drives the handshake (ack ATN, ready, byte-ack, EOI-ack); talker drives the bits we sample | **bidirectional** (open-drain) |
|
||||||
| RESET | C64 drives; we react | **input** |
|
| RESET | C64 drives; we react | **input** |
|
||||||
| SRQ | unused on stock C64 | not connected |
|
| SRQ | unused on stock C64 | not connected |
|
||||||
|
|
||||||
So we drive **exactly one** bus line (DATA) and read three. No turnaround, no
|
So we **actively drive exactly one** bus line (DATA, open-drain) and sense the
|
||||||
|
rest — but DATA doubles as an *input* during bit sampling (we release it to Hi-Z,
|
||||||
|
then read the talker's bits), which is why it is a single bidirectional pin (§3).
|
||||||
|
No turnaround, no
|
||||||
EOI generation, no 60 µs talker timing. The only timing the device generates is
|
EOI generation, no 60 µs talker timing. The only timing the device generates is
|
||||||
the 1 ms ATN ack and the per-byte ack — both forgiving. The tight constraint is
|
the 1 ms ATN ack and the per-byte ack — both forgiving. The tight constraint is
|
||||||
*sampling* the C64's ~20 µs bit clock while receiving (see §6).
|
*sampling* the C64's ~20 µs bit clock while receiving (see §6).
|
||||||
@ -75,34 +78,50 @@ the 1 ms ATN ack and the per-byte ack — both forgiving. The tight constraint i
|
|||||||
|
|
||||||
## 3. Hardware
|
## 3. Hardware
|
||||||
|
|
||||||
### 3.1 Interface circuit (per the research, simplified for one output)
|
### 3.1 Interface circuit (single bidirectional DATA pin, sd2iec-style)
|
||||||
|
|
||||||
- **DATA (drive):** open-collector driver. Two equivalent options:
|
Design decision: DATA is a **single bidirectional pin** doing **open-drain
|
||||||
- **7406/74LS06** inverting OC buffer: Pi GPIO → 7406 input → bus. Pi HIGH ⇒ bus
|
emulation**, mirroring the sd2iec one-line scheme rather than a separate
|
||||||
pulled low (asserted). *(Software must invert.)*
|
drive-pin + sense-pin pair. Because the Pi is **not 5 V-tolerant**, the line goes
|
||||||
- **NPN transistor** (2N3904/BC547): Pi GPIO → 1 kΩ → base; emitter → GND;
|
through a **bidirectional MOSFET level shifter** (BSS138 + pull-ups — the NXP
|
||||||
collector → DATA line. Pi HIGH ⇒ transistor on ⇒ bus low. Same inversion.
|
AN10441 / common "logic level converter" topology). sd2iec needs no shifter only
|
||||||
- Use whichever is on hand; the 7406 also gives spare drivers for later (CLK,
|
because its AVR runs at 5 V; the 3.3 V Pi does.
|
||||||
talker mode). Recommend the **7406** to match the eventual full device.
|
|
||||||
- **ATN, CLK, RESET (sense):** resistor divider 5 V→~3.1 V into each Pi input
|
- **DATA (single pin, bidirectional):** GPIO 18 ↔ level shifter ↔ IEC DATA. The Pi
|
||||||
(e.g. 3.3 kΩ top / 2.2 kΩ to GND). **No inversion** in sensing: bus low (0 V,
|
pin is never a push-pull driver of the bus; it emulates open-drain:
|
||||||
asserted) ⇒ Pi reads LOW.
|
- **Assert** (pull bus low): GPIO 18 = **output LOW** → shifter pulls bus to 0 V.
|
||||||
- 100 nF bypass cap across the 7406 VCC–GND. Common GND between C64 IEC pin 2 and Pi.
|
- **Release / read**: GPIO 18 = **input (Hi-Z)** → the bus pull-ups define the
|
||||||
|
level and GPIO 18 reads the bus. **Non-inverting:** bus low (asserted) ⇒ Pi
|
||||||
|
reads LOW. (Releasing to Hi-Z is what lets us sample the talker's bits in §6.)
|
||||||
|
- Direction is flipped in the hot path via the BCM `GPFSEL` register — a single
|
||||||
|
register write, ~tens of ns, negligible against the 20 µs bit window.
|
||||||
|
- **ATN, CLK, RESET (sense, input only):** route through the **same kind of
|
||||||
|
shifter** (remaining channels of a 4-channel BSS138 board). Pi side always input.
|
||||||
|
**Non-inverting:** bus low (asserted) ⇒ Pi reads LOW. *(A resistor divider also
|
||||||
|
works for these input-only lines, but reusing the shifter gives a uniform, fully
|
||||||
|
in-spec 3.3 V swing and sidesteps the marginal divider voltages flagged in the
|
||||||
|
kernel research.)*
|
||||||
|
- **Recommended part:** one 4-channel bidirectional level-shifter board carries all
|
||||||
|
four lines (DATA bidirectional; ATN/CLK/RESET input-only). No 7406, no transistor,
|
||||||
|
no hand-matched dividers — low side to Pi 3.3 V, high side to bus 5 V.
|
||||||
|
- 100 nF bypass cap on the shifter VCC pins. Common GND between C64 IEC pin 2 and Pi.
|
||||||
- **Do not connect bus 5 V to any Pi pin directly — Pi GPIO is not 5 V tolerant.**
|
- **Do not connect bus 5 V to any Pi pin directly — Pi GPIO is not 5 V tolerant.**
|
||||||
|
|
||||||
### 3.2 Pin map (Pi Zero 2 W, 40-pin header)
|
### 3.2 Pin map (Pi Zero 2 W, 40-pin header)
|
||||||
|
|
||||||
| IEC signal | Pi GPIO (BCM) | Header pin | Direction | Logic note |
|
| IEC signal | Pi GPIO (BCM) | Header pin | Direction | Logic note |
|
||||||
|------------|---------------|------------|-----------|------------|
|
|------------|---------------|------------|-----------|------------|
|
||||||
| ATN | GPIO 2 | 3 | input (divider) | bus low = Pi low = asserted |
|
| ATN | GPIO 2 | 3 | input (via shifter) | bus low = Pi low = asserted |
|
||||||
| CLK | GPIO 17 | 11 | input (divider) | bus low = Pi low = asserted |
|
| CLK | GPIO 17 | 11 | input (via shifter) | bus low = Pi low = asserted |
|
||||||
| DATA (in) | GPIO 18 | 12 | output → 7406 → bus | Pi HIGH = bus asserted (inverted) |
|
| DATA | GPIO 18 | 12 | **bidirectional (via shifter)** | open-drain: assert = output LOW, release/read = input. bus low = Pi low = asserted |
|
||||||
| RESET | GPIO 3 | 5 | input (divider) | bus low = Pi low = asserted |
|
| RESET | GPIO 3 | 5 | input (via shifter) | bus low = Pi low = asserted |
|
||||||
| GND | — | 6 (or any) | — | tie to IEC pin 2 |
|
| GND | — | 6 (or any) | — | tie to IEC pin 2 and shifter GND |
|
||||||
|
|
||||||
> Convention used in code: a helper layer converts electrical reads/writes into
|
> Convention used in code: a helper layer (`iec_lines.h`) converts electrical
|
||||||
> **logical** `asserted=True / released=False` so the rest of the code reasons in
|
> reads/writes into **logical** `asserted=True / released=False`. With the
|
||||||
> the protocol's true/false sense and never juggles the inversions inline.
|
> non-inverting level shifter the mapping is direct — assert ⇒ DATA GPIO output
|
||||||
|
> LOW, release ⇒ DATA GPIO input (Hi-Z), and a Pi LOW read on any line means
|
||||||
|
> asserted. No 7406 inversion to juggle.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -205,9 +224,11 @@ never juggles inversions inline (mirrors the original userspace plan, now in C):
|
|||||||
|
|
||||||
- `atn_asserted()` — true when ATN GPIO reads low
|
- `atn_asserted()` — true when ATN GPIO reads low
|
||||||
- `clk_asserted()` — true when CLK GPIO reads low
|
- `clk_asserted()` — true when CLK GPIO reads low
|
||||||
- `data_in()` — read DATA line (the talker drives it during bit transfer)
|
- `data_in()` — read DATA line (the talker drives it during bit transfer; only
|
||||||
- `data_assert()` / `data_release()` — drive DATA true / float it; encapsulates
|
valid after `data_release()` has set the pin to Hi-Z input)
|
||||||
the 7406 inversion (assert ⇒ Pi GPIO HIGH)
|
- `data_assert()` / `data_release()` — assert DATA (set GPIO 18 **output LOW**) /
|
||||||
|
release it (set GPIO 18 **input / Hi-Z**, letting the bus float high). Open-drain
|
||||||
|
emulation through the level shifter; **non-inverting** (no 7406 to invert)
|
||||||
- `reset_asserted()` — true when RESET GPIO reads low
|
- `reset_asserted()` — true when RESET GPIO reads low
|
||||||
|
|
||||||
### 5.2 Userspace record stream (`device.py`)
|
### 5.2 Userspace record stream (`device.py`)
|
||||||
@ -416,7 +437,7 @@ Requirements:
|
|||||||
| Even in-kernel, busy-poll mid-byte gets preempted/IRQ'd and garbles a bit | Medium | Disable local IRQs/preemption for the duration of a byte; if still marginal, isolcpus + steer other IRQs away (raspbiec pattern); last resort `PREEMPT_RT`. Quantify in Phase 0.5. |
|
| Even in-kernel, busy-poll mid-byte gets preempted/IRQ'd and garbles a bit | Medium | Disable local IRQs/preemption for the duration of a byte; if still marginal, isolcpus + steer other IRQs away (raspbiec pattern); last resort `PREEMPT_RT`. Quantify in Phase 0.5. |
|
||||||
| Keeping IRQs off too long for a byte harms system stability | Medium | Bound the off-window to one byte (~few hundred µs); re-enable between bytes. A design constraint to validate in Phase 0.5. |
|
| Keeping IRQs off too long for a byte harms system stability | Medium | Bound the off-window to one byte (~few hundred µs); re-enable between bytes. A design constraint to validate in Phase 0.5. |
|
||||||
| Kernel module build/ABI churn against Raspberry Pi OS kernel | Medium | Build against installed kernel headers; pin kernel version; document in `kernel-notes.md`. |
|
| Kernel module build/ABI churn against Raspberry Pi OS kernel | Medium | Build against installed kernel headers; pin kernel version; document in `kernel-notes.md`. |
|
||||||
| 7406 inversion / divider miswire | Medium | `iec_lines.h` logical layer isolates it; module `selftest` ioctl toggles DATA and reads ATN/CLK with the C64 off. |
|
| Level-shifter wiring / DATA direction-flip bug | Medium | `iec_lines.h` logical layer isolates assert/release/read; module `selftest` ioctl drives DATA (output LOW), releases to Hi-Z and reads it back, and reads ATN/CLK with the C64 off. Confirm Hi-Z release truly floats so the talker's bits read through. |
|
||||||
| C64 has JiffyDOS | Low (printer rarely uses it) | Out of scope; document. Standard protocol still works for a printer device. |
|
| C64 has JiffyDOS | Low (printer rarely uses it) | Out of scope; document. Standard protocol still works for a printer device. |
|
||||||
| ATN response missed | Low | Hardware IRQ pulls DATA in the ISR; 1 ms budget is ample for kernel interrupt latency. |
|
| ATN response missed | Low | Hardware IRQ pulls DATA in the ISR; 1 ms budget is ample for kernel interrupt latency. |
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user