@vessel-dsp/compiler 0.0.0-stage → 0.3.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/README.md +118 -2
- package/dist/bake.d.ts +38 -0
- package/dist/bake.d.ts.map +1 -0
- package/dist/bake.js +101 -0
- package/dist/bake.js.map +1 -0
- package/dist/bbd-clock.d.ts +171 -0
- package/dist/bbd-clock.d.ts.map +1 -0
- package/dist/bbd-clock.js +1750 -0
- package/dist/bbd-clock.js.map +1 -0
- package/dist/block-row.d.ts +51 -0
- package/dist/block-row.d.ts.map +1 -0
- package/dist/block-row.js +17 -0
- package/dist/block-row.js.map +1 -0
- package/dist/bypass.d.ts +3 -0
- package/dist/bypass.d.ts.map +1 -0
- package/dist/bypass.js +228 -0
- package/dist/bypass.js.map +1 -0
- package/dist/compile.d.ts +24 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +348 -0
- package/dist/compile.js.map +1 -0
- package/dist/converter-scale.d.ts +14 -0
- package/dist/converter-scale.d.ts.map +1 -0
- package/dist/converter-scale.js +133 -0
- package/dist/converter-scale.js.map +1 -0
- package/dist/couple.d.ts +28 -0
- package/dist/couple.d.ts.map +1 -0
- package/dist/couple.js +567 -0
- package/dist/couple.js.map +1 -0
- package/dist/dangling-active-terminal.d.ts +47 -0
- package/dist/dangling-active-terminal.d.ts.map +1 -0
- package/dist/dangling-active-terminal.js +542 -0
- package/dist/dangling-active-terminal.js.map +1 -0
- package/dist/declared-program.d.ts +23 -0
- package/dist/declared-program.d.ts.map +1 -0
- package/dist/declared-program.js +387 -0
- package/dist/declared-program.js.map +1 -0
- package/dist/denomination.d.ts +48 -0
- package/dist/denomination.d.ts.map +1 -0
- package/dist/denomination.js +27 -0
- package/dist/denomination.js.map +1 -0
- package/dist/device-laws.d.ts +237 -0
- package/dist/device-laws.d.ts.map +1 -0
- package/dist/device-laws.js +3513 -0
- package/dist/device-laws.js.map +1 -0
- package/dist/diagnostics.d.ts +13 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +19 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/emit.d.ts +8 -0
- package/dist/emit.d.ts.map +1 -0
- package/dist/emit.js +43 -0
- package/dist/emit.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/firmware-class.d.ts +69 -0
- package/dist/firmware-class.d.ts.map +1 -0
- package/dist/firmware-class.js +20 -0
- package/dist/firmware-class.js.map +1 -0
- package/dist/fixtures/circuits.d.ts +1742 -0
- package/dist/fixtures/circuits.d.ts.map +1 -0
- package/dist/fixtures/circuits.js +13896 -0
- package/dist/fixtures/circuits.js.map +1 -0
- package/dist/fixtures/expected.d.ts +261 -0
- package/dist/fixtures/expected.d.ts.map +1 -0
- package/dist/fixtures/expected.js +315 -0
- package/dist/fixtures/expected.js.map +1 -0
- package/dist/fixtures/index.d.ts +4 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +8 -0
- package/dist/fixtures/index.js.map +1 -0
- package/dist/fixtures/registry.d.ts +52 -0
- package/dist/fixtures/registry.d.ts.map +1 -0
- package/dist/fixtures/registry.js +341 -0
- package/dist/fixtures/registry.js.map +1 -0
- package/dist/generic-tube-fit.d.ts +12 -0
- package/dist/generic-tube-fit.d.ts.map +1 -0
- package/dist/generic-tube-fit.js +45 -0
- package/dist/generic-tube-fit.js.map +1 -0
- package/dist/grounded-clock-supply.d.ts +13 -0
- package/dist/grounded-clock-supply.d.ts.map +1 -0
- package/dist/grounded-clock-supply.js +45 -0
- package/dist/grounded-clock-supply.js.map +1 -0
- package/dist/identify.d.ts +50 -0
- package/dist/identify.d.ts.map +1 -0
- package/dist/identify.js +319 -0
- package/dist/identify.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/inert-controls.d.ts +15 -0
- package/dist/inert-controls.d.ts.map +1 -0
- package/dist/inert-controls.js +266 -0
- package/dist/inert-controls.js.map +1 -0
- package/dist/latch-seed.d.ts +53 -0
- package/dist/latch-seed.d.ts.map +1 -0
- package/dist/latch-seed.js +257 -0
- package/dist/latch-seed.js.map +1 -0
- package/dist/link.d.ts +7 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +270 -0
- package/dist/link.js.map +1 -0
- package/dist/lower.d.ts +79 -0
- package/dist/lower.d.ts.map +1 -0
- package/dist/lower.js +1855 -0
- package/dist/lower.js.map +1 -0
- package/dist/netlist.d.ts +79 -0
- package/dist/netlist.d.ts.map +1 -0
- package/dist/netlist.js +4746 -0
- package/dist/netlist.js.map +1 -0
- package/dist/non-executable-clock-drivers.d.ts +8 -0
- package/dist/non-executable-clock-drivers.d.ts.map +1 -0
- package/dist/non-executable-clock-drivers.js +33 -0
- package/dist/non-executable-clock-drivers.js.map +1 -0
- package/dist/open-category.d.ts +98 -0
- package/dist/open-category.d.ts.map +1 -0
- package/dist/open-category.js +111 -0
- package/dist/open-category.js.map +1 -0
- package/dist/over-driven-node.d.ts +33 -0
- package/dist/over-driven-node.d.ts.map +1 -0
- package/dist/over-driven-node.js +188 -0
- package/dist/over-driven-node.js.map +1 -0
- package/dist/part-catalog.d.ts +15 -0
- package/dist/part-catalog.d.ts.map +1 -0
- package/dist/part-catalog.js +6712 -0
- package/dist/part-catalog.js.map +1 -0
- package/dist/part-number.d.ts +32 -0
- package/dist/part-number.d.ts.map +1 -0
- package/dist/part-number.js +80 -0
- package/dist/part-number.js.map +1 -0
- package/dist/partition.d.ts +7 -0
- package/dist/partition.d.ts.map +1 -0
- package/dist/partition.js +242 -0
- package/dist/partition.js.map +1 -0
- package/dist/port-full-scale.d.ts +70 -0
- package/dist/port-full-scale.d.ts.map +1 -0
- package/dist/port-full-scale.js +235 -0
- package/dist/port-full-scale.js.map +1 -0
- package/dist/pot-orientation.d.ts +114 -0
- package/dist/pot-orientation.d.ts.map +1 -0
- package/dist/pot-orientation.js +551 -0
- package/dist/pot-orientation.js.map +1 -0
- package/dist/power-domain-control.d.ts +40 -0
- package/dist/power-domain-control.d.ts.map +1 -0
- package/dist/power-domain-control.js +142 -0
- package/dist/power-domain-control.js.map +1 -0
- package/dist/proxy-declaration.d.ts +121 -0
- package/dist/proxy-declaration.d.ts.map +1 -0
- package/dist/proxy-declaration.js +50 -0
- package/dist/proxy-declaration.js.map +1 -0
- package/dist/registry.d.ts +323 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +192 -0
- package/dist/registry.js.map +1 -0
- package/dist/sparse-schedule.d.ts +65 -0
- package/dist/sparse-schedule.d.ts.map +1 -0
- package/dist/sparse-schedule.js +421 -0
- package/dist/sparse-schedule.js.map +1 -0
- package/dist/speaker-load.d.ts +38 -0
- package/dist/speaker-load.d.ts.map +1 -0
- package/dist/speaker-load.js +97 -0
- package/dist/speaker-load.js.map +1 -0
- package/dist/stage-coverage.d.ts +21 -0
- package/dist/stage-coverage.d.ts.map +1 -0
- package/dist/stage-coverage.js +124 -0
- package/dist/stage-coverage.js.map +1 -0
- package/dist/stamp-partition.d.ts +314 -0
- package/dist/stamp-partition.d.ts.map +1 -0
- package/dist/stamp-partition.js +472 -0
- package/dist/stamp-partition.js.map +1 -0
- package/dist/supply-reference.d.ts +19 -0
- package/dist/supply-reference.d.ts.map +1 -0
- package/dist/supply-reference.js +66 -0
- package/dist/supply-reference.js.map +1 -0
- package/dist/supply-short.d.ts +32 -0
- package/dist/supply-short.d.ts.map +1 -0
- package/dist/supply-short.js +118 -0
- package/dist/supply-short.js.map +1 -0
- package/dist/supply-stamps.d.ts +51 -0
- package/dist/supply-stamps.d.ts.map +1 -0
- package/dist/supply-stamps.js +363 -0
- package/dist/supply-stamps.js.map +1 -0
- package/dist/terminal-role.d.ts +109 -0
- package/dist/terminal-role.d.ts.map +1 -0
- package/dist/terminal-role.js +46 -0
- package/dist/terminal-role.js.map +1 -0
- package/dist/terminal-roles.d.ts +59 -0
- package/dist/terminal-roles.d.ts.map +1 -0
- package/dist/terminal-roles.js +92 -0
- package/dist/terminal-roles.js.map +1 -0
- package/dist/transformer.d.ts +181 -0
- package/dist/transformer.d.ts.map +1 -0
- package/dist/transformer.js +476 -0
- package/dist/transformer.js.map +1 -0
- package/dist/types.d.ts +3157 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/unbounded-operating-point.d.ts +35 -0
- package/dist/unbounded-operating-point.d.ts.map +1 -0
- package/dist/unbounded-operating-point.js +181 -0
- package/dist/unbounded-operating-point.js.map +1 -0
- package/dist/unexecuted-region.d.ts +3 -0
- package/dist/unexecuted-region.d.ts.map +1 -0
- package/dist/unexecuted-region.js +122 -0
- package/dist/unexecuted-region.js.map +1 -0
- package/dist/unimplemented-control-role.d.ts +3 -0
- package/dist/unimplemented-control-role.d.ts.map +1 -0
- package/dist/unimplemented-control-role.js +61 -0
- package/dist/unimplemented-control-role.js.map +1 -0
- package/dist/unreachable-output.d.ts +3 -0
- package/dist/unreachable-output.d.ts.map +1 -0
- package/dist/unreachable-output.js +97 -0
- package/dist/unreachable-output.js.map +1 -0
- package/dist/unreadable-terminal-role.d.ts +67 -0
- package/dist/unreadable-terminal-role.d.ts.map +1 -0
- package/dist/unreadable-terminal-role.js +409 -0
- package/dist/unreadable-terminal-role.js.map +1 -0
- package/dist/unverified-pinout.d.ts +27 -0
- package/dist/unverified-pinout.d.ts.map +1 -0
- package/dist/unverified-pinout.js +121 -0
- package/dist/unverified-pinout.js.map +1 -0
- package/package.json +75 -5
package/README.md
CHANGED
|
@@ -1,3 +1,119 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @vessel-dsp/compiler
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Headless circuit compiler turning `.vdsp` / `CircuitDocument` schematic data into compiled simulation `Program` ROMs for VesselDSP. Pure TypeScript, deterministic, rate independent, headless. It depends on `@vessel-dsp/core` and `js-yaml` only.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
`@vessel-dsp/compiler` 0.3.0 is on npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add @vessel-dsp/compiler
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Subpath exports: `.` (compile, registries, the supply-stamp join, and every `Program` type), `./diagnostics` (the report-only reach into stages for instruments), and `./fixtures` (the synthetic circuits the engine is graded on, with hand-computed expectations).
|
|
14
|
+
|
|
15
|
+
## Minimal example
|
|
16
|
+
|
|
17
|
+
Compile takes `.vdsp` source text and an optional part registry. It returns a result, never a throw, for a document it cannot use. The fixtures below ship with the package under `./fixtures`, so this runs as written:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { compile, emptyRegistry } from "@vessel-dsp/compiler";
|
|
21
|
+
import { resistorDivider } from "@vessel-dsp/compiler/fixtures";
|
|
22
|
+
|
|
23
|
+
const result = compile(resistorDivider, { registry: emptyRegistry });
|
|
24
|
+
|
|
25
|
+
if (result.status === "ok") {
|
|
26
|
+
console.log("Compiled program blocks:", result.program.blocks.length);
|
|
27
|
+
console.log("Warnings:", result.warnings.length);
|
|
28
|
+
} else {
|
|
29
|
+
console.error("Compilation refused:", result.reasons);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
Compiled program blocks: 1
|
|
35
|
+
Warnings: 0
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Which registry to pass
|
|
39
|
+
|
|
40
|
+
`compile(source, options)` defaults to `emptyRegistry` when no registry is given. The empty registry models only device class laws (resistor, capacitor, plain op-amp stages) and refuses parts that need catalog identity. `pedalPartCatalog` is the corpus facing catalog injected by scripts and tests.
|
|
41
|
+
|
|
42
|
+
Over the eight fixtures used in the guides (`resistorDivider`, `rcLowPass`, `diodeClipper`, `invertingAmplifier`, `potDivider`, `commonEmitterAmplifier`, `emitterFollower`, `triodeGainStage`), both registries compile 8 of 8. Measured over the 121 top level packets in the artifacts corpus (read only, not committed):
|
|
43
|
+
|
|
44
|
+
- `emptyRegistry`: 74 of 121 compile.
|
|
45
|
+
- `pedalPartCatalog`: 119 of 121 compile. The two refusals are `boss-dd-3t.vdsp` and `boss-dd-5.vdsp`, both undisclosed DSP parts.
|
|
46
|
+
|
|
47
|
+
Use `pedalPartCatalog` for real pedal packets. Use `emptyRegistry` only to measure what works with no part knowledge, or for synthetic device class probes.
|
|
48
|
+
|
|
49
|
+
One refusal shape, for the `unknownChip` fixture with `emptyRegistry`:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
[{ "stage": "device-laws", "device": "U1",
|
|
53
|
+
"reason": "integrated circuit has no model: its part number
|
|
54
|
+
\"UNKNOWN-PART-XYZ\" matched no registry entry, and a declared
|
|
55
|
+
class may not supply a macro for a part whose identity is unresolved" }]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Result shape
|
|
59
|
+
|
|
60
|
+
`compile` returns `CompileResult`:
|
|
61
|
+
|
|
62
|
+
- `{ status: "ok", program, warnings }`. Warnings never block a program. A pedal with a dead knob is still worth hearing, but it must not be silent about it. Each warning carries a closed `code` callers can switch on, plus human readable `detail`.
|
|
63
|
+
- `{ status: "unsupported", reasons }`. Each reason is a `CompileRefusal` with `stage` (`netlist`, `device-laws`, `partition`, `lower`, or `link`), `device` (component id or null), and a human readable `reason`. `device-laws` means a part could not be modelled; any other stage means the document itself does not support a program. A floating wiper that disconnects the circuit refuses at the `link` stage instead of warning.
|
|
64
|
+
|
|
65
|
+
Only a `StageRefusal` becomes a result. Anything else (a compiler bug) propagates as a throw, because a bug reported as an unsupported pedal would be a wrong answer about someone's circuit.
|
|
66
|
+
|
|
67
|
+
`compileToArtifact(source, options)` runs `compile` and pairs it with `emit`: `{ result, artifact }` where `artifact` is null unless the result is ok. `emit` renders the deterministic serializable form (`{ text, digest }`). There is no public `decode` in 0.2.0: program JSON is consumed by the consoles.
|
|
68
|
+
|
|
69
|
+
`readNetlist(source, options?)` runs the first stage only: document text to a law free `Netlist` with `inputJack`/`outputJack` overrides and `parseQuantity` for SI values (`10k` to 10000).
|
|
70
|
+
|
|
71
|
+
## The Program
|
|
72
|
+
|
|
73
|
+
A `Program` is rate independent: it carries no sample rate. The runtime supplies the rate at `prepare()`. Top level keys:
|
|
74
|
+
|
|
75
|
+
`formatVersion` (6 in 0.2.0), `requiredOperators`, `requiredModels`, `costPredictors`, `blocks`, `order`, `controls`, `ports`, `supplyReference`, `portReferenceVolts`, `portFullScaleVolts`, `stageCoverage`, `portImpedanceOhms`, `bypass`.
|
|
76
|
+
|
|
77
|
+
Compiled `Program`s carry `formatVersion` 6. Named I/O ports and the `bufferProgram` bypass are deferred to a later `formatVersion`; from here any change to `Program`, the `Stamp` union, `ProgramJson.cpp` or `Program.h` is a package minor bump.
|
|
78
|
+
|
|
79
|
+
`requiredOperators` lists every stamp operator the executed blocks present, sorted, so a runtime can refuse by name at load. `requiredModels` lists every macro DSP model id the same way. `order` is the block execution order and may omit blocks `blocks` retains. `supplyReference` is `negative-ground`, `positive-ground`, `dual-rail`, or `unpowered`, derived from `dc-source` signs. `stageCoverage` is `instrument`, `preamp`, `speaker-electrical`, or `miked`. `portFullScaleVolts` (a ceiling derived from the rails) and `portReferenceVolts` (the 0 dBFS voltage the jack declares) are different quantities; either entry may be `null`.
|
|
80
|
+
|
|
81
|
+
`commonEmitterAmplifier` with `emptyRegistry` compiles to 1 block (`order: ["analog:0"]`) with stamp kinds `dc-source` 1, `capacitor` 2, `conductance` 5, `bjt` 1, `input-source` 1. The `potDivider` fixture declares one control, `Level` (`taper: linear`, default 0.5, continuous so `positions: null`, role `output-level`, label `VOLUME`).
|
|
82
|
+
|
|
83
|
+
Each `mna` block carries `nodeIds` (row to source node map), `auxCount`, `stamps`, `stampPartition`, `sparseSchedule`, `stateCount`, `linear`, `controlFree`, `eliminate`, input/output nodes, and operating point seeds. A `macro` block carries a DSP `modelId` with parameters instead of stamps.
|
|
84
|
+
|
|
85
|
+
## Supply stamps
|
|
86
|
+
|
|
87
|
+
`resolveSupplyStamps(source, program)` joins the document power domains to the compiled `dc-source` stamps. It takes the same source text the program was compiled from and returns `{ supplies, refused }`. Only rails in an external DC domain with `derivation: direct` and `role: main-supply` are candidates; derived rails (divider, regulator, inverter, doubler, isolated) keep their compiled values.
|
|
88
|
+
|
|
89
|
+
The closed refusal reasons are `no-power-section`, `mains-ac-source`, `unknown-source-kind`, `source-kind-conflict`, `derived-rail`, `rail-not-main-supply`, `no-stamp-for-rail`, `ambiguous-stamp`. Callers switch on `reason`; `detail` is prose for a human report. Mains fed amp B+ rails are refused by design: a battery profile must never be applied downstream of a rectifier.
|
|
90
|
+
|
|
91
|
+
See the Compiler guide for a worked `resolveSupplyStamps` example, and the [runtime supply-control design note](https://github.com/vessel-dsp/core/blob/main/docs/design/runtime-supply-control.md) for the full design.
|
|
92
|
+
|
|
93
|
+
## Public exports
|
|
94
|
+
|
|
95
|
+
Values on `.`:
|
|
96
|
+
|
|
97
|
+
| Name | What it is |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `compile` | Compile, or explain the refusal. Never throws for a document it cannot use. |
|
|
100
|
+
| `compileToArtifact` | `compile` plus `emit`, paired as `{ result, artifact }`. |
|
|
101
|
+
| `emit` | Render a `Program` to its serializable `{ text, digest }` artifact. |
|
|
102
|
+
| `readNetlist` | First stage only: source text to a law free netlist. |
|
|
103
|
+
| `parseQuantity` | Parse a quantity to SI base units (`10k` to 10000). |
|
|
104
|
+
| `emptyRegistry` | No part knowledge; measures what device class laws alone cover. |
|
|
105
|
+
| `pedalPartCatalog` | The catalog corpus facing scripts inject. |
|
|
106
|
+
| `foldPartId` | Fold case and separators (`MN-3007` is `mn3007`). |
|
|
107
|
+
| `foldToken` | Fold case and whitespace for typed vocabulary values. |
|
|
108
|
+
| `registryEntryFor` | Entry lookup for a device. |
|
|
109
|
+
| `registryLawFor` | The law a registered part supplies for a device. |
|
|
110
|
+
| `canonicalPartId` | Canonical part identity spelling. |
|
|
111
|
+
| `zenerCatalogPartIds` | Part ids the catalog treats as zeners. |
|
|
112
|
+
| `resolveSupplyStamps` | Join document power domains to compiled `dc-source` stamps. |
|
|
113
|
+
| `attachDeviceLaws` | Stage 2: attach laws to every netlist device. |
|
|
114
|
+
|
|
115
|
+
Types on `.` (import with `import type`): `CompileOptions`, `CompileResult`, `CompileSuccess`, `CompileFailure`, `CompileRefusal`, every `Program`/`Block`/`Stamp`/`Control`/cost type (`Program`, `Block`, `Stamp`, `OperatorKind`, `Control`, `ControlId`, `TaperKind`, `Ports`, `CostPredictors`, `NodeId`, `GROUND`, and the rest in `types.ts`), and the supply-join types (`SupplyAddress`, `ResolvedSupply`, `RefusedSupply`, `SupplyResolution`, `SupplyRefusalReason`).
|
|
116
|
+
|
|
117
|
+
`./diagnostics` (report-only reach into stages for instruments, not consumer API): `blockRow`, `describeRow`, `nodeAt`, `stampNodes`, `stampInSourceNodes`, `perSample`, `SILICON_FORWARD_BETA`, `SILICON_SATURATION_CURRENT`, `THERMAL_VOLTAGE`, `findBistableLatches`, `OPEN_RULES`, `connectedToBothPorts`, `isPacketDisconnected`, `outputDependence`, `validateProxy`, `recordedReads`, `withRecordedReads`, `clearRecordedReads`, `speakerImpedance`, `speakerImpedanceMagnitude`, `speakerOnePort`, `clockTimingNodes`, `deriveBbdDelayFromNetlist`, `findClockDriverDevice`, plus the accompanying types (`PerSample`, `BistableLatch`, `NetGraph`, `FirmwareClass`, and the violation types).
|
|
118
|
+
|
|
119
|
+
`./fixtures` (248 exports: synthetic circuits, hand-computed expectations, and their registries): `resistorDivider`, `rcLowPass`, `diodeClipper`, `invertingAmplifier`, `potDivider`, `commonEmitterAmplifier`, `emitterFollower`, `triodeGainStage`, `unknownChip`, `dividerGain`, `potGainAt`, `fixtureRegistry`, and the rest. These are the only circuits whose answers are known independently of the instruments, which is what makes them shippable.
|
package/dist/bake.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Block } from "./types";
|
|
2
|
+
/** Why a block's realisation may not be baked, naming the block and the failing flag. */
|
|
3
|
+
export type BakeRefusal = {
|
|
4
|
+
readonly block: string;
|
|
5
|
+
readonly reason: string;
|
|
6
|
+
};
|
|
7
|
+
export type BakeDecision = {
|
|
8
|
+
readonly outcome: "may-bake";
|
|
9
|
+
} | {
|
|
10
|
+
readonly outcome: "refused";
|
|
11
|
+
readonly refusal: BakeRefusal;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* May this block's realisation be derived once and reused across samples?
|
|
15
|
+
*
|
|
16
|
+
* Only when `linear && controlFree` both hold. Checked in that order because a `linear`
|
|
17
|
+
* failure is the more fundamental one -- a nonlinear block has no fixed realisation to derive
|
|
18
|
+
* at all, `linear && controlFree` or not -- so naming it first is the more useful refusal even
|
|
19
|
+
* though a real block can fail either independently (see `bake.test.ts`'s four-quadrant cases,
|
|
20
|
+
* matching `lower.test.ts`'s own `resistorDivider`/`potDivider`/`switchedDivider`/
|
|
21
|
+
* `diodeClipper` fixtures for `linear`/`controlFree`'s own precedent).
|
|
22
|
+
*/
|
|
23
|
+
export declare function bakeDecisionFor(block: Extract<Block, {
|
|
24
|
+
readonly kind: "mna";
|
|
25
|
+
}>,
|
|
26
|
+
/**
|
|
27
|
+
* Whether every supply this block references holds still across the samples the realisation
|
|
28
|
+
* would be reused over.
|
|
29
|
+
*
|
|
30
|
+
* `true` for every block the compiler builds today — a rail is ground or a node inside this
|
|
31
|
+
* block's own matrix, and sag inside the matrix is already exact in a linear realisation.
|
|
32
|
+
* The reducer must pass `false` the day a rail is driven from outside the block, whichever
|
|
33
|
+
* shape that plumbing takes.
|
|
34
|
+
*/
|
|
35
|
+
supply?: {
|
|
36
|
+
readonly static: boolean;
|
|
37
|
+
}): BakeDecision;
|
|
38
|
+
//# sourceMappingURL=bake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bake.d.ts","sourceRoot":"","sources":["../src/bake.ts"],"names":[],"mappings":"AAmDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,yFAAyF;AACzF,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AAElE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAC/C;;;;;;;;GAQG;AACH,MAAM,GAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAqB,GACrD,YAAY,CA6Bd"}
|
package/dist/bake.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Spec clause 5: `linear && controlFree`, jointly, as the precondition for baking a
|
|
2
|
+
// realisation -- and NOTHING ELSE. No new field: `Block.linear` and `Block.controlFree`
|
|
3
|
+
// already exist (`src/compiler/types.ts`, computed in `lower.ts` from the exhaustive,
|
|
4
|
+
// `never`-bound `stampNeedsNewton`/`stampControl` classifiers), and this file is the
|
|
5
|
+
// instruction to read them as a conjunction rather than separately, at the one place a
|
|
6
|
+
// reduction may ever be baked and reused across samples.
|
|
7
|
+
//
|
|
8
|
+
// **This gate has no caller today, and that is honest rather than incomplete.** Nothing in
|
|
9
|
+
// this compiler reduces an `mna` block into a state-space realisation -- that is step 5's own
|
|
10
|
+
// future work, and it does not exist yet (build-order steps 4 and 5 are unbuilt; clause 4,
|
|
11
|
+
// declared output nodes, has nothing to govern until something reduces). `bakeDecisionFor`
|
|
12
|
+
// is the precondition function that future stage MUST call before it bakes anything, and it
|
|
13
|
+
// is written, tested and wired into the plan's documentation now rather than left implicit,
|
|
14
|
+
// so the precondition cannot be forgotten the day someone builds the reducer. The insertion
|
|
15
|
+
// point is between `lower`/`couple` and `link` in `compile.ts`'s pipeline -- after a block's
|
|
16
|
+
// stamps are final and its `linear`/`controlFree` flags are settled, before anything is
|
|
17
|
+
// scheduled to run.
|
|
18
|
+
//
|
|
19
|
+
// **Why the conjunction, not either flag alone.** `linear-core-state-space-gate` measured
|
|
20
|
+
// H0 (a linear reduction is exact) fully holding, and H2 ("linear is sufficient on its own")
|
|
21
|
+
// false: its `load-shift` mutation -- a realisation derived at one load, evaluated at
|
|
22
|
+
// another -- errs 80% of the signal (`4.19e-02` against a `5.23e-02` reference), because a
|
|
23
|
+
// pot sits *inside* the matrix a realisation is derived from, so a knob move is exactly the
|
|
24
|
+
// kind of topology change a baked realisation cannot track without re-deriving. `linear`
|
|
25
|
+
// alone would have let that 80% error ship silently -- see `bake.test.ts`'s reproduction of
|
|
26
|
+
// this shape on `potDivider`, and `pipeline.test.ts` for the same shape measured end to end.
|
|
27
|
+
//
|
|
28
|
+
// **The supply gap, closed 2026-09-02 as a third condition rather than a fourth flag.** A block
|
|
29
|
+
// can be `linear && controlFree` and still reference a rail that moves with the audio, because
|
|
30
|
+
// `controlFree` is about controls and says nothing about supply state. This used to be recorded
|
|
31
|
+
// here as an undecided gap waiting on the rail-port design. It is not: the gate can refuse the
|
|
32
|
+
// case without knowing how a moving rail will eventually be *plumbed*, and refusing it is what
|
|
33
|
+
// the reducer needs.
|
|
34
|
+
//
|
|
35
|
+
// **Why the caller supplies the answer instead of the block carrying a flag.** A rail that moves
|
|
36
|
+
// cannot cross a block boundary today -- every supply a block references is either ground or a
|
|
37
|
+
// node inside its own matrix, and a rail sagging *inside* a linear block is already exact in the
|
|
38
|
+
// realisation, because the sag is part of the linear system being derived. So a `supplyStatic`
|
|
39
|
+
// field on `Block` would be a constant `true` with no way to test it, and this repository's
|
|
40
|
+
// evidence rule asks for a check that can fail for the reason claimed. Taking it as an argument
|
|
41
|
+
// makes the future reducer state the answer at the point it bakes, keeps the Program contract
|
|
42
|
+
// (and its C++ mirror) unchanged, and is testable today by passing `false`.
|
|
43
|
+
//
|
|
44
|
+
// **What is still open is the port design, and it is deliberately not decided here.** Whether a
|
|
45
|
+
// dynamic rail becomes a fourth port kind or folds into `coupled` is an architecture question
|
|
46
|
+
// whose evidence does not exist yet -- `thoughts/shared/experiments/power-domain-rail-sag-contract/`
|
|
47
|
+
// was written to produce exactly that evidence (sign convention, multi-rail summing, the DK
|
|
48
|
+
// rail-in/current-out contract) and has never been run. This gate is correct under either answer:
|
|
49
|
+
// whichever one lands sets `supply.static` to `false` for a block whose rail is driven from
|
|
50
|
+
// outside it.
|
|
51
|
+
/**
|
|
52
|
+
* May this block's realisation be derived once and reused across samples?
|
|
53
|
+
*
|
|
54
|
+
* Only when `linear && controlFree` both hold. Checked in that order because a `linear`
|
|
55
|
+
* failure is the more fundamental one -- a nonlinear block has no fixed realisation to derive
|
|
56
|
+
* at all, `linear && controlFree` or not -- so naming it first is the more useful refusal even
|
|
57
|
+
* though a real block can fail either independently (see `bake.test.ts`'s four-quadrant cases,
|
|
58
|
+
* matching `lower.test.ts`'s own `resistorDivider`/`potDivider`/`switchedDivider`/
|
|
59
|
+
* `diodeClipper` fixtures for `linear`/`controlFree`'s own precedent).
|
|
60
|
+
*/
|
|
61
|
+
export function bakeDecisionFor(block,
|
|
62
|
+
/**
|
|
63
|
+
* Whether every supply this block references holds still across the samples the realisation
|
|
64
|
+
* would be reused over.
|
|
65
|
+
*
|
|
66
|
+
* `true` for every block the compiler builds today — a rail is ground or a node inside this
|
|
67
|
+
* block's own matrix, and sag inside the matrix is already exact in a linear realisation.
|
|
68
|
+
* The reducer must pass `false` the day a rail is driven from outside the block, whichever
|
|
69
|
+
* shape that plumbing takes.
|
|
70
|
+
*/
|
|
71
|
+
supply = { static: true }) {
|
|
72
|
+
if (!block.linear) {
|
|
73
|
+
return {
|
|
74
|
+
outcome: "refused",
|
|
75
|
+
refusal: {
|
|
76
|
+
block: block.id,
|
|
77
|
+
reason: `block "${block.id}" is not linear, so it has no fixed realisation to derive at all -- it must keep iterating Newton every sample`,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (!block.controlFree) {
|
|
82
|
+
return {
|
|
83
|
+
outcome: "refused",
|
|
84
|
+
refusal: {
|
|
85
|
+
block: block.id,
|
|
86
|
+
reason: `block "${block.id}" is linear but not control-free, so a realisation baked at one control position would be wrong at another -- linear-core-state-space-gate measured this at 80% of the signal (load-shift). Refuse to bake and keep solving the per-sample stamps until re-derivation on control change or knob-grid tabulation exists`,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (!supply.static) {
|
|
91
|
+
return {
|
|
92
|
+
outcome: "refused",
|
|
93
|
+
refusal: {
|
|
94
|
+
block: block.id,
|
|
95
|
+
reason: `block "${block.id}" is linear and control-free but references a supply that moves with the audio, and a realisation derived at one rail voltage is wrong at another for the same reason a pot position is -- the rail sits inside the matrix the realisation is derived from. Refuse to bake until the rail is an input the realisation can be re-derived against`,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { outcome: "may-bake" };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=bake.js.map
|
package/dist/bake.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bake.js","sourceRoot":"","sources":["../src/bake.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,wFAAwF;AACxF,sFAAsF;AACtF,qFAAqF;AACrF,uFAAuF;AACvF,yDAAyD;AACzD,EAAE;AACF,2FAA2F;AAC3F,8FAA8F;AAC9F,2FAA2F;AAC3F,2FAA2F;AAC3F,4FAA4F;AAC5F,4FAA4F;AAC5F,4FAA4F;AAC5F,6FAA6F;AAC7F,wFAAwF;AACxF,oBAAoB;AACpB,EAAE;AACF,0FAA0F;AAC1F,6FAA6F;AAC7F,sFAAsF;AACtF,2FAA2F;AAC3F,4FAA4F;AAC5F,yFAAyF;AACzF,4FAA4F;AAC5F,6FAA6F;AAC7F,EAAE;AACF,gGAAgG;AAChG,+FAA+F;AAC/F,gGAAgG;AAChG,+FAA+F;AAC/F,+FAA+F;AAC/F,qBAAqB;AACrB,EAAE;AACF,iGAAiG;AACjG,+FAA+F;AAC/F,iGAAiG;AACjG,+FAA+F;AAC/F,4FAA4F;AAC5F,gGAAgG;AAChG,8FAA8F;AAC9F,4EAA4E;AAC5E,EAAE;AACF,gGAAgG;AAChG,8FAA8F;AAC9F,qGAAqG;AACrG,4FAA4F;AAC5F,kGAAkG;AAClG,4FAA4F;AAC5F,cAAc;AAcd;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC9B,KAA+C;AAC/C;;;;;;;;GAQG;AACH,SAAuC,EAAE,MAAM,EAAE,IAAI,EAAE;IAEvD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO;YACN,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE;gBACR,KAAK,EAAE,KAAK,CAAC,EAAE;gBACf,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,gHAAgH;aAC1I;SACD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO;YACN,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE;gBACR,KAAK,EAAE,KAAK,CAAC,EAAE;gBACf,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,wTAAwT;aAClV;SACD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO;YACN,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE;gBACR,KAAK,EAAE,KAAK,CAAC,EAAE;gBACf,MAAM,EAAE,UAAU,KAAK,CAAC,EAAE,iVAAiV;aAC3W;SACD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import type { ControlId, Device, DeviceKind, Netlist, NodeId, TaperKind } from "./types";
|
|
2
|
+
import type { PartRegistry } from "./registry";
|
|
3
|
+
export type ClockDriverFamily = "CD4047" | "MN3101" | "MN3102" | "unknown";
|
|
4
|
+
export type BbdClockDerivationOutcome = {
|
|
5
|
+
readonly outcome: "derived";
|
|
6
|
+
readonly delaySeconds: number;
|
|
7
|
+
readonly rOhms: number;
|
|
8
|
+
readonly cFarads: number;
|
|
9
|
+
readonly fClockHz: number;
|
|
10
|
+
readonly family: ClockDriverFamily;
|
|
11
|
+
readonly stages: number;
|
|
12
|
+
readonly formulaConstant: number;
|
|
13
|
+
readonly offsetSeconds: number;
|
|
14
|
+
readonly controlId: ControlId | null;
|
|
15
|
+
readonly taper: TaperKind;
|
|
16
|
+
readonly ohmsAtControlMin: number;
|
|
17
|
+
readonly ohmsAtControlMax: number;
|
|
18
|
+
} | {
|
|
19
|
+
readonly outcome: "no-clock-driver";
|
|
20
|
+
} | {
|
|
21
|
+
readonly outcome: "refused";
|
|
22
|
+
readonly reason: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Device kinds that can *drive* a timing node rather than merely set it.
|
|
26
|
+
*
|
|
27
|
+
* A resistor, a capacitor and a potentiometer are the timing network — a pot is a knob, which is
|
|
28
|
+
* control-rate and already carried as `controlId`. Anything on this list sitting on the timing
|
|
29
|
+
* network is steering it at signal rate, which is how an LFO reaches a BBD clock.
|
|
30
|
+
*
|
|
31
|
+
* `diode` is deliberately absent: `mxr-carbon-copy` clamps its CD4047 timing node with `D5` to
|
|
32
|
+
* ground, and a clamp is not a modulator. `ic` is absent because the clock driver is itself an
|
|
33
|
+
* `ic` on its own timing pins.
|
|
34
|
+
*/
|
|
35
|
+
export declare const ACTIVE_TIMING_KINDS: ReadonlySet<DeviceKind>;
|
|
36
|
+
/**
|
|
37
|
+
* Devices actively steering this clock driver's timing network, by id.
|
|
38
|
+
*
|
|
39
|
+
* The discrimination this exists for, measured 2026-08-29 across the corpus: `mxr-carbon-copy`
|
|
40
|
+
* and `boss-dm-2` carry only resistors, capacitors and pots on their timing nodes, so their
|
|
41
|
+
* derived delays are a property of the circuit. `boss-ce-5` carries **`Q8`'s emitter directly
|
|
42
|
+
* on oscillator node 42**, so the frequency is set by that transistor's current and the R·C
|
|
43
|
+
* arithmetic reads a resistor that is not what times the oscillator.
|
|
44
|
+
*/
|
|
45
|
+
export declare function activeTimingDrivers(clockDevice: Device, netlist: Netlist, registry: PartRegistry): readonly string[];
|
|
46
|
+
export type ClockModulationSource = {
|
|
47
|
+
readonly outcome: "resolved";
|
|
48
|
+
readonly steeredBy: string;
|
|
49
|
+
readonly node: NodeId;
|
|
50
|
+
} | {
|
|
51
|
+
readonly outcome: "none";
|
|
52
|
+
} | {
|
|
53
|
+
readonly outcome: "refused";
|
|
54
|
+
readonly reason: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* The node an LFO reaches a modulated BBD clock on: the steering device's **control** terminal.
|
|
58
|
+
*
|
|
59
|
+
* **Not the timing node.** That is the point of this function. The timing node carries the
|
|
60
|
+
* oscillator's own waveform at the clock rate — for a chorus, ~100 kHz, far above anything a
|
|
61
|
+
* 48 kHz host can sample — so reading it as a modulation source would alias garbage into the
|
|
62
|
+
* delay length. The control terminal carries the LFO and nothing else: on `boss-ce-2` that is
|
|
63
|
+
* `Q5`'s base, which the DEPTH pot reaches through `Q4` and `D1`.
|
|
64
|
+
*
|
|
65
|
+
* Deliberately strict. Exactly one steering device with one resolvable control terminal, and
|
|
66
|
+
* that terminal may not sit on ground or on the timing network itself. Anything else refuses by
|
|
67
|
+
* name and leaves the delay static, because a guess here is a sweep of the wrong thing.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveClockModulationSource(bbdDevice: Device, netlist: Netlist, registry: PartRegistry): ClockModulationSource;
|
|
70
|
+
/**
|
|
71
|
+
* The nodes a clock driver's own timing network hangs on, by family.
|
|
72
|
+
*
|
|
73
|
+
* Exported because `scripts/report-bbd-architecture.ts` asks the same question and answered it
|
|
74
|
+
* with a private copy of the role vocabulary, which **under-reported immediately**: an MN3102
|
|
75
|
+
* spelling its pins `oscillatorinput`/`oscillatoroutput`/`clockcontrol` (`boss-bf-2`) matched
|
|
76
|
+
* none of the canonical `ox1`/`ox2`/`ox3` tokens, so a driver the compiler finds read as absent
|
|
77
|
+
* in the report. One enumerator, shared, is the same conclusion `stampNodes` reached.
|
|
78
|
+
*
|
|
79
|
+
* Role tokens are compared as whole values after folding, never by substring, and the MN310x
|
|
80
|
+
* branch admits the registry's own alias spellings through `oscillatorRoleTokens`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function clockTimingNodes(device: Device, registry: PartRegistry): ReadonlySet<NodeId>;
|
|
83
|
+
export declare function identifyClockFamily(device: Device): ClockDriverFamily;
|
|
84
|
+
export declare function findClockDriverDevice(netlist: Netlist): Device | null;
|
|
85
|
+
export declare function deriveBbdDelayFromNetlist(bbdDevice: Device, netlist: Netlist, stages: number, registry: PartRegistry): BbdClockDerivationOutcome;
|
|
86
|
+
/**
|
|
87
|
+
* Open-OX2 clock law (CE-2 first slice, 2026-09-28).
|
|
88
|
+
*
|
|
89
|
+
* The form the MN3101 datasheet never drew: OX2 left open (N.C.) and a single
|
|
90
|
+
* relaxation loop across the OX1→OX3 inverter pair — a timing capacitor
|
|
91
|
+
* between OX3 and OX1 charged through a pull-up on OX1 and discharged by a
|
|
92
|
+
* transistor the OX3 side drives, with the LFO setting the restart level
|
|
93
|
+
* through a diode. `boss-ce-2` v1.25 is the corpus case.
|
|
94
|
+
*
|
|
95
|
+
* Family constants (per-packet R and C come from the netlist):
|
|
96
|
+
* - `OPEN_OX2_VDD_VOLTS`: the driver's supply span, 9 V nominal from the
|
|
97
|
+
* packet's own supply port (the filtered rail measures 8.967 V, 0.4%,
|
|
98
|
+
* disclosed and immaterial beside the threshold sensitivity).
|
|
99
|
+
* - `OPEN_OX2_VTH_VOLTS`: solved 2026-09-28 for 110 kHz at the measured
|
|
100
|
+
* Depth-0 divider level 1.565 V against a scope specimen (DIYstompboxes
|
|
101
|
+
* 2011, one rough forum reading, disclosed), inside the 3.4–5.6 V window
|
|
102
|
+
* the MN3101 p.60 example table allows. Re-solve, never tune: procedure in
|
|
103
|
+
* `docs/todo-archive/2026-09-28-ce2-clock-law-analysis.md`.
|
|
104
|
+
* - `OPEN_OX2_VF_VOLTS`: generic-diode forward drop, disclosed typical.
|
|
105
|
+
* - `OPEN_OX2_FLOOR_VOLTS`: yank-minus-kick bottom under datasheet OX3 drive
|
|
106
|
+
* (R_OH ≈ 667 Ω / R_OL ≈ 500 Ω from the I_OH2/I_OL2 minimums): a ~7 V OX3
|
|
107
|
+
* step kicks ~6.2 V through 47 pF against cited diode maxima, landing near
|
|
108
|
+
* −5.3 V — below the D1 floor at every measured divider level, so the D1
|
|
109
|
+
* branch binds everywhere. Same max() form as the analysis, not a deletion.
|
|
110
|
+
*/
|
|
111
|
+
export declare const OPEN_OX2_VDD_VOLTS = 9;
|
|
112
|
+
export declare const OPEN_OX2_VTH_VOLTS = 4.757;
|
|
113
|
+
export declare const OPEN_OX2_VF_VOLTS = 0.65;
|
|
114
|
+
export declare const OPEN_OX2_FLOOR_VOLTS = -5.35;
|
|
115
|
+
export type OpenOx2ClockLawOutcome = {
|
|
116
|
+
readonly outcome: "recognized";
|
|
117
|
+
readonly slowNode: NodeId;
|
|
118
|
+
readonly steeredBy: string;
|
|
119
|
+
readonly rOhms: number;
|
|
120
|
+
readonly cFarads: number;
|
|
121
|
+
} | {
|
|
122
|
+
readonly outcome: "absent";
|
|
123
|
+
readonly reason: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Recognise the open-OX2 relaxation form by connectivity, never by names or
|
|
127
|
+
* prose: an MN3101-family driver with OX2 touched by nothing but its own pin,
|
|
128
|
+
* one capacitor bridging OX3 to OX1, one pull-up resistor from OX1 to the
|
|
129
|
+
* driver's own supply pin, one resistor from OX3 into a grounded-emitter
|
|
130
|
+
* transistor's base, that transistor's collector on a pulled-up discharge
|
|
131
|
+
* node back into OX1 through a diode, and one diode from OX1 into a
|
|
132
|
+
* divider-fed slow node.
|
|
133
|
+
*
|
|
134
|
+
* Anything else is `absent` with the failed check named, and the caller falls
|
|
135
|
+
* back to the existing star/gate derivation untouched. In particular the
|
|
136
|
+
* pre-rewire collapse (capacitor on OX1–OX2), a transistor sitting directly
|
|
137
|
+
* on a timing node (the modulated refusal owns that), and the MN3102 two-leg
|
|
138
|
+
* form (a different oscillator; no corpus case) all read absent here.
|
|
139
|
+
*/
|
|
140
|
+
export declare function deriveOpenOx2ClockLaw(netlist: Netlist, registry: PartRegistry): OpenOx2ClockLawOutcome;
|
|
141
|
+
/**
|
|
142
|
+
* Princeton Technology PT2399 delay time from external VCO resistance R (in Ohms).
|
|
143
|
+
*
|
|
144
|
+
* Princeton PT2399 datasheet, TABLE 1: RESISTOR/DELAY TIME VALUES (V1.4, Oct 2005;
|
|
145
|
+
* the same 28-row table is reprinted in V1.1, V1.2 and V1.6; the packet-local V1.9,
|
|
146
|
+
* Mar 2022, drops the table but still says "Please refer to Table 1 for the
|
|
147
|
+
* Resistor/Delay Time values"). Note 1 under the table states R in Ohms, so the
|
|
148
|
+
* last row's "0.5" is 0.5 Ohms (pin 6 effectively grounded, 31.3 ms), not 0.5 kOhms.
|
|
149
|
+
*
|
|
150
|
+
* The table is linear in R: with pin 6 held at 2.5 V, the page
|
|
151
|
+
* https://electrosmash.mas-effects.com/pt2399-analysis gives
|
|
152
|
+
* I_pin6 (mA) = 28.65 / (Delay_ms - 29.70), i.e. Delay_ms = 29.70 + 11.46 * R_kOhms,
|
|
153
|
+
* which reproduces all 28 cited rows within 4 ms (worst row: 27.6 kOhms, 346.0 ms
|
|
154
|
+
* predicted vs 342 ms cited). That linear form is what this returns.
|
|
155
|
+
*
|
|
156
|
+
* Deliberately no clamp and no hard maximum: the cited source states none. Quality
|
|
157
|
+
* degrades past about 350 ms (the table's own THD reaches 1.0% at 342 ms), but the
|
|
158
|
+
* delay keeps growing with R, so this extrapolates the line rather than clipping it.
|
|
159
|
+
*/
|
|
160
|
+
export declare function pt2399DelayFromOhms(rOhms: number): number;
|
|
161
|
+
/**
|
|
162
|
+
* Derives delaySeconds and dynamic control mapping for PT2399 digital delay chips
|
|
163
|
+
* by tracing the series resistor/potentiometer network connected to VCO Pin 6.
|
|
164
|
+
*/
|
|
165
|
+
export declare function derivePt2399DelayFromNetlist(device: Device, netlist: Netlist): BbdClockDerivationOutcome;
|
|
166
|
+
/**
|
|
167
|
+
* Derives delaySeconds and dynamic control mapping for Mitsubishi M50195P digital echo LSI
|
|
168
|
+
* by tracing the inverter oscillator timing network connected to CLK1.
|
|
169
|
+
*/
|
|
170
|
+
export declare function deriveM50195DelayFromNetlist(device: Device, netlist: Netlist): BbdClockDerivationOutcome;
|
|
171
|
+
//# sourceMappingURL=bbd-clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bbd-clock.d.ts","sourceRoot":"","sources":["../src/bbd-clock.ts"],"names":[],"mappings":"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"}
|