Skip to content

Commit 2d8b529

Browse files
committed
Document the internal design in readme
1 parent 2385915 commit 2d8b529

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

src/current/rp2350/README.md

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ Temporarly, for this to work, we need to add a PWM chanell in Arduino-FOC rp2040
1414

1515

1616
TODO:
17-
* Init a the DMA or IRQ to read samples from PIO.
18-
* Activate the push of adc data in PIO program (disabled for tests)
1917
* Find a way to setup the trigger PWM from the driver, or change the arduino-foc lib.
20-
18+
* Select an available PIO and state machine automaticaly.
2119

2220

2321
# Example:
@@ -58,6 +56,8 @@ void setup() {
5856
5957
void loop() {
6058
motor.move(target_velocity);
59+
PhaseCurrent_s phaseCurrents = curr.getPhaseCurrents();
60+
Serial.printf("%d, %3.3lf, %3.3lf, %3.3lf\r\n", micros(), phaseCurrents.a, phaseCurrents.b, phaseCurrents.c);
6161
}
6262
```
6363

@@ -69,4 +69,59 @@ Note for self, on my setup:
6969
```
7070
export PIOASM="$HOME/.arduino15/packages/rp2040/tools/pqt-pioasm/4.1.0-1aec55e/pioasm"
7171
"$PIOASM" -v 1 bu79100g_parallel3.pio bu79100g_parallel3.pio.h
72-
```
72+
```
73+
74+
# Internal Design
75+
76+
This library uses:
77+
- One PIO state machine
78+
- Two DMA channels
79+
- One PWM (and associated GPIO)
80+
81+
82+
## Trigger Pin
83+
84+
For low-side current measurement, the ADC must sample at the center of the low pulse of the phase PWM signals.
85+
To achieve this, a *trigger pin* is configured as an auxiliary PWM output, synchronized with the motor PWM but with a fixed duty cycle.
86+
87+
- This PWM can be mapped to any pin.
88+
- It does **not** need to be connected to external hardware.
89+
- The duty cycle is tuned to compensate for the dummy sampling enforced by the BU79100G-LA ADC.
90+
91+
In the future, this trigger mechanism could also be used to synchronize other types of ADCs.
92+
93+
**Note (TODO/WIP):** Trigger pin handling is not yet implemented in the driver. Proper synchronization during driver initialization still needs to be added.
94+
95+
96+
## PIO
97+
98+
The PIO waits for a rising edge on the trigger pin to start two SPI transfers:
99+
1. A **dummy conversion** (required by the BU79100G-LA when operating at low frequency).
100+
2. The **actual ADC conversion**.
101+
102+
Data is captured from 3 SPI data lines in parallel. A 4th line is also sampled but discarded; it can be freely repurposed as a normal GPIO (input or output).
103+
104+
The PIO writes results to its FIFO as two interleaved 32-bit words in the format: [a1 b1 c1 d1 a2 b2 c2 d2 .... ]
105+
106+
## DMA
107+
108+
Two DMA channels are configured to move data from the PIO FIFO into system memory:
109+
110+
- **dma_a** transfers incoming 32-bit words into a ring buffer.
111+
- The buffer size must be a power of two.
112+
- The buffer address must be aligned with its total size.
113+
114+
- **dma_b** is chained to **dma_a**. It resets the transfer count of **dma_a** by performing a single 32-bit transfer.
115+
- **dma_a** is then chained back to **dma_b**, creating a self-sustaining loop without CPU intervention.
116+
117+
118+
## CPU Access to Samples
119+
120+
The CPU can asynchronously access the most recent samples by reading the current DMA write address.
121+
122+
- If the address is **even**, read samples at positions *n-2* and *n-1*.
123+
- If the address is **odd**, read samples at positions *n-3* and *n-2*.
124+
- Address wraparound is handled.
125+
126+
Since the PIO delivers interleaved data, the CPU must de-interleave it. On an RP2350, de-interleaving and copying takes approximately **1 µs** per sample set.
127+

0 commit comments

Comments
 (0)