Lots of doc updates
parent
e38da22af5
commit
c4755a233a
|
@ -1128,9 +1128,6 @@
|
|||
(junction (at 71.12 91.44) (diameter 0) (color 0 0 0 0)
|
||||
(uuid a46fcb78-250d-4921-8a87-b2519402d8d7)
|
||||
)
|
||||
(junction (at 129.54 149.86) (diameter 0) (color 0 0 0 0)
|
||||
(uuid a89299d5-5402-4f09-9626-aed55f7bcb19)
|
||||
)
|
||||
(junction (at 71.12 81.28) (diameter 0) (color 0 0 0 0)
|
||||
(uuid aabfff1a-dfb8-4c4c-9f00-4d2023e80623)
|
||||
)
|
||||
|
@ -1424,6 +1421,10 @@
|
|||
(stroke (width 0) (type dash_dot) (color 72 72 72 1))
|
||||
(uuid 526975f9-28b2-44bb-9fe9-c9267356a875)
|
||||
)
|
||||
(polyline (pts (xy 19.05 135.89) (xy 19.05 156.21))
|
||||
(stroke (width 0) (type dash))
|
||||
(uuid 53e88d33-3f12-441c-9809-ed9a17708df3)
|
||||
)
|
||||
|
||||
(bus (pts (xy 260.35 82.55) (xy 260.35 86.36))
|
||||
(stroke (width 0) (type default))
|
||||
|
@ -1778,10 +1779,6 @@
|
|||
(uuid d12306e0-a553-4ecb-88eb-4915b66e3cd9)
|
||||
)
|
||||
|
||||
(wire (pts (xy 129.54 157.48) (xy 129.54 149.86))
|
||||
(stroke (width 0) (type default))
|
||||
(uuid d451bbb0-9df7-4113-b76f-c2fba12c0a33)
|
||||
)
|
||||
(wire (pts (xy 71.12 81.28) (xy 71.12 76.2))
|
||||
(stroke (width 0) (type default))
|
||||
(uuid d451c38e-19df-4720-a790-d167fcb3dff6)
|
||||
|
@ -1893,6 +1890,10 @@
|
|||
(stroke (width 0) (type default))
|
||||
(uuid fa50c382-0229-4bdc-9705-9e1c11adbc78)
|
||||
)
|
||||
(polyline (pts (xy 19.05 135.89) (xy 58.42 135.89))
|
||||
(stroke (width 0) (type dash))
|
||||
(uuid fb5bc4bc-6f46-407a-830b-17683886ee71)
|
||||
)
|
||||
(polyline (pts (xy 242.57 97.79) (xy 242.57 95.25))
|
||||
(stroke (width 0) (type dash))
|
||||
(uuid fbe88ee7-e830-43ee-a0c5-fef329707871)
|
||||
|
@ -1956,6 +1957,10 @@
|
|||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
(uuid 413f4c64-5596-4695-820b-f338519a1161)
|
||||
)
|
||||
(text "IMPLEMENATION NOTE" (at 20.32 139.7 0)
|
||||
(effects (font (size 1.27 1.27) (thickness 0.254) bold) (justify left bottom))
|
||||
(uuid 4969b734-3d23-44ee-b68c-2af7bedb09e7)
|
||||
)
|
||||
(text "U5" (at 19.05 195.58 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
(uuid 49c37a0c-6206-4162-90bc-c6c4ef1879f5)
|
||||
|
@ -2067,6 +2072,11 @@
|
|||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
(uuid d3e36383-c510-4f37-a6d8-5cc3d140c7af)
|
||||
)
|
||||
(text "Implementers may tie R16 to the\nmicrocontroller supply rail instead\nof +5V and then omit R17, substantially\nreducing standby power consumption."
|
||||
(at 20.32 154.94 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
(uuid d6f7b278-7bd6-4471-9c6f-a381c7c98913)
|
||||
)
|
||||
(text "Low charge injection variant of 74HCT4051. Critical for performance"
|
||||
(at 57.15 190.5 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left bottom))
|
||||
|
|
Binary file not shown.
176
doc/TOO.md
176
doc/TOO.md
|
@ -19,28 +19,194 @@ and layout quality.
|
|||
|
||||
## Hardware
|
||||
|
||||
TODO: reference design here
|
||||
TODO: reference design here, need a nice crisp PNG
|
||||
|
||||
### Reference chopper
|
||||
|
||||
Analog switch `U1B` implements a constant-impedance reference chopper. By
|
||||
sending the voltage reference either into the 0V virtual ground of the
|
||||
integrator or directly into ground, it ensures that the load on the voltage
|
||||
reference is stable — the AC peak-to-peak component is equal to the integrator
|
||||
offset voltage divided by the slope resistor, or about 12 nA on 30 µA. This
|
||||
stability ensures that the voltage reference output impedance and load
|
||||
regulation error do not come into play, which provides a few LSBs improvement
|
||||
to INL with typical voltage references.
|
||||
|
||||
### Integrator and ramp inverter
|
||||
|
||||
Op amp `U2A` is connected as an inverting integrator, so when a positive-going
|
||||
pulse is applied to it, a negative-going ramp is produced. Because the reference
|
||||
chopper fully disconnects the reference during the space period rather than
|
||||
applying 0V, `U2A`'s input offset voltage is not integrated into an error term;
|
||||
only the leakage current is integrated. This will eventually add up to an
|
||||
error, so the discharge switch is held engaged whenever possible, and because
|
||||
`U2` is a low-leakage JFET op amp, the resulting error is negligible.
|
||||
|
||||
Analog switch `U1C` discharges the integrating capacitor through `R4` when
|
||||
switched on; `R4` is also shared with the sample-and-hold circuit as the
|
||||
charging resistor for negative ramps.
|
||||
|
||||
Because there are few options for noninverting integrators that provide the
|
||||
speed and precision needed, a second op amp `U2B` inverts the inverted ramp,
|
||||
producing a positive-going ramp. The resistor ratio on this inverter will
|
||||
induce a gain error; the tuning comparator senses the _positive_ ramp in order
|
||||
to prioritize this most likely polarity (TODO, #3).
|
||||
|
||||
### Tuning comparator
|
||||
|
||||
Comparator `U5` detects whether the positive-going ramp has crossed the
|
||||
reference voltage. `R15` adds hysteresis, and `D1` blocks the hysteresis on
|
||||
the leading edge so the switching threshold is as accurate as possible
|
||||
(TODO rev 1.1 uses an RC circuit instead).
|
||||
|
||||
The pulldown resistor R17 reduces the output voltage from 5V to 3.3V. As per
|
||||
the note in the schematic, it can be removed if R16 pulls up to the system
|
||||
IO voltage.
|
||||
|
||||
### Polarity switch and output multiplexer
|
||||
|
||||
Analog switch `U1A` selects between the positive and negative ramps; it may
|
||||
be omitted for non-bipolar designs. The selected ramp is steered to the
|
||||
output capacitors through multiplexer `U3`, which is inhibited until the ramp
|
||||
has stabilized.
|
||||
|
||||
### Sample-and-hold amplifiers
|
||||
|
||||
The output capacitor bank holds the output voltages in between pulse transfers.
|
||||
To stabilize the output voltage, they are buffered by high-impedance op amps
|
||||
`U4A` etc. Charging current is limited by resistor `R4` (for negative ramps)
|
||||
or `R5` (for positive ramps); these are placed on the pre-multiplexer side to
|
||||
reduce part count.
|
||||
|
||||
## Firmware
|
||||
|
||||
### Layer 1: low-level DAC driver
|
||||
|
||||
TODO: state diagram here
|
||||
The low-level driver steps the external hardware through its various states.
|
||||
It is responsible for discharging the integrator, generating a pulse to be
|
||||
integrated into a ramp, waiting for the integrator to stabilize, and finally,
|
||||
either transferring the final ramp value to the output or using it for tuning.
|
||||
|
||||
```
|
||||
┌────┐
|
||||
│IDLE│ ◄───────────────────────────────┐
|
||||
└┬───┘ │
|
||||
│ │
|
||||
│emit or tune │
|
||||
▼ │
|
||||
┌─────────┐ │
|
||||
│DISCHARGE│ │
|
||||
└┬────────┘ │
|
||||
│ │
|
||||
│ │
|
||||
┌┴────┐ │
|
||||
│PULSE│ │
|
||||
└┬────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌─────────┐tune ┌────────────────┐ │
|
||||
│STABILIZE├─────►│Evaluate tuning ├────┘
|
||||
└┬────────┘ └────────────────┘ ▲
|
||||
│emit │
|
||||
▼ │
|
||||
┌────────┐ │
|
||||
│TRANSFER├─────────────────────────────┘
|
||||
└────────┘
|
||||
```
|
||||
|
||||
### Layer 2: tuning driver
|
||||
|
||||
TODO: state diagram here
|
||||
The tuning driver, which is also part of `timdac_ll.c`, exists as an
|
||||
intermediate layer between the low-level and high-level driver. It is triggered
|
||||
by the high-level driver, and itself triggers the emission of one pulse from
|
||||
the low-level driver. The pulse it emits, and the comparator output at the
|
||||
end of that pulse, is used as the comparison in a binary-search successive
|
||||
approximation. Each time it runs, the range is narrowed by half, until it has
|
||||
been narrowed down to a single value. Once this happens, the resulting
|
||||
measurement is pushed into a low-pass filter, which smooths the tuning over
|
||||
time to reduce noise, and the output of this filter provides the tuning
|
||||
scale factor.
|
||||
|
||||
### Layer 3: scan driver
|
||||
```
|
||||
┌────┐
|
||||
│Idle│ ◄──────────────────────────────────────────┐
|
||||
└┬───┘ │
|
||||
│timdac_ll_tune() │
|
||||
▼ │
|
||||
┌──────────────┐ no ┌──────────────────┐ │
|
||||
│top/bot valid?├────────┤Reinit to 65535, 0├──────┘
|
||||
└┬─────────────┘ └──────────────────┘ ▲
|
||||
│yes │
|
||||
▼ │
|
||||
┌────────────────┐ no ┌──────────────────────┐ │
|
||||
│top/bot unequal?├─────►│Tuning is complete ├──┘
|
||||
└┬───────────────┘ │Push top/bot into the │ ▲
|
||||
│yes │tuning low-pass filter│ │
|
||||
│ └──────────────────────┘ │
|
||||
▼ │
|
||||
┌──────────────────────────────────────┐ │
|
||||
│Start a pulse with width = (top+bot)/2│ │
|
||||
└┬─────────────────────────────────────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌─────────────────────────────────┐ │
|
||||
│Read the tuning comparator output│ │
|
||||
└┬───────────────┬────────────────┘ │
|
||||
│ramp<vref │ramp>vref │
|
||||
│ │ │
|
||||
▼ ▼ │
|
||||
┌─────────┐ ┌─────────┐ │
|
||||
│bot = mid│ │top = mid│ │
|
||||
└┬────────┘ └┬────────┘ │
|
||||
│ │ │
|
||||
└─────────────► └────────────────────────────────┘
|
||||
```
|
||||
|
||||
TODO: state diagram here
|
||||
### Layer 3: scan (high-level) driver
|
||||
|
||||
The high-level driver sequences all of the above continuously through its
|
||||
various states. It is triggered by the timer stop interrupt, and always starts
|
||||
the timer, so it will continue forever (TODO, #1).
|
||||
|
||||
If the first tuning cycle has not yet completed, it will always initiate the
|
||||
next phase, so that outputs are never scanned prior to a tuning. It will also
|
||||
initiate a scan periodically, as defined by `TIMDAC_TUNE_INTERVAL`. If there
|
||||
is no tuning needed, it will next check to see if a channel is in the
|
||||
queue-jump pending slot, and if there is, this channel is emitted next. When
|
||||
this happens, the queue-jump slot is "blanked" for one cycle so that rarely
|
||||
updated channels always get scanned. If none of these less common scenarios
|
||||
occur, the next channel in a simple round-robin scan sequence is emitted.
|
||||
|
||||
```
|
||||
┌─────────────────────┐ ┌──────────────────────┐
|
||||
│Step low-level driver│◄───────────────────┤Wait for timer to stop│
|
||||
└┬────────────────────┘ └──────────────────────┘
|
||||
│ ▲
|
||||
▼ │
|
||||
┌──────────────────────┐ no ┌─────────────┐ │
|
||||
│First tuning complete?├─────►│Initiate tune├───────────────────┘
|
||||
└┬─────────────────────┘ └─────────────┘ ▲
|
||||
│yes ▲ │
|
||||
▼ │ │
|
||||
┌────────────────────────┐ yes │ │
|
||||
│Reached tuning interval?├───────────┘ │
|
||||
└┬───────────────────────┘ │
|
||||
│no │
|
||||
▼ │
|
||||
yes ┌────────────────────────┐ │
|
||||
┌───┤Queue-jump slot blanked?│ │
|
||||
│ └┬───────────────────────┘ │
|
||||
│ │no │
|
||||
│ ▼ │
|
||||
│ ┌───────────────────────────┐ yes ┌─────────────────┐ │
|
||||
│ │Channel in queue-jump slot?├─────►│Emit queue jumper│ │
|
||||
│ └┬──────────────────────────┘ └┬────────────────┘ │
|
||||
│ │no │ │
|
||||
│ │ ▼ │
|
||||
│ │ ┌─────────────────────┐ │
|
||||
│ │ │Blank queue-jump slot├──────┘
|
||||
│ ▼ └─────────────────────┘ ▲
|
||||
│ ┌─────────────────┐ │
|
||||
└──►│Emit next channel├─────────────────────────────────────────────┘
|
||||
└─────────────────┘
|
||||
```
|
||||
|
|
|
@ -65,7 +65,7 @@ void timdac_ll_init(void)
|
|||
|
||||
bool timdac_ll_tune(void)
|
||||
{
|
||||
if (_tune_sar_top == 0 || _tune_sar_bot == UINT16_MAX)
|
||||
if (_tune_sar_top < _tune_sar_bot)
|
||||
{
|
||||
// Start fresh.
|
||||
_tune_sar_top = UINT16_MAX;
|
||||
|
|
Loading…
Reference in New Issue