Skip to content

Commit 39806d8

Browse files
committed
Add a PIO program for ADC bu79100g, work in progress
1 parent cad5809 commit 39806d8

File tree

5 files changed

+153
-7
lines changed

5 files changed

+153
-7
lines changed

src/current/rp2350/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,16 @@
66
Implementation of current sensing on RP2350 using the PIO to read SPI based ADCs.
77

88

9+
Temporarly, for this to work, we need to add a PWM chanell in Arduino-FOC rp2040 hardware specific files. The duty cyctle needs to be computed to trigger the ADC at the right-time.
10+
The PWM pin is hardcoded to GPIO11 for now.
911

12+
13+
14+
## Compilling the PIO program
15+
To manually compile the PIO files (generating a .pio.h from a pio), you need to instal pioasm.
16+
Note for self, on my setup:
17+
18+
```
19+
export PIOASM="$HOME/.arduino15/packages/rp2040/tools/pqt-pioasm/4.1.0-1aec55e/pioasm"
20+
"$PIOASM" -v 1 bu79100g_parallel3.pio bu79100g_parallel3.pio.h
21+
```

src/current/rp2350/RP2350PIOCurrentSense.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#include "RP2350PIOCurrentSense.h"
22

3-
RP2350PIOCurrentSense::RP2350PIOCurrentSense(float gain, uint32_t max_adc_value, int pinA, int pinB, int pinC) : CurrentSense() {
4-
this->pinA = pinA;
5-
this->pinB = pinB;
6-
this->pinC = pinC;
3+
RP2350PIOCurrentSense::RP2350PIOCurrentSense(float gain, uint32_t max_adc_value, int pinSCK, int pinCSB, int pinD0) : CurrentSense() {
4+
this->pinSCK = pinSCK;
5+
this->pinCSB = pinCSB;
6+
this->pinD0 = pinD0;
7+
this->pinD1 = pinD0+1;
8+
this->pinD2 = pinD0+2;
79
this->gain_a = gain;
810
this->gain_b = gain;
911
this->gain_c = gain;
1012
this->max_adc_value = max_adc_value;
13+
1114
};
1215

1316

@@ -19,13 +22,50 @@
1922
// TODO check that pins are valid for PIO use (e.g. consecutive pins on same bank)
2023
// TODO check that driver is linked
2124

22-
// TODO init PIO
25+
// Done init PIO
2326
// TODO init ADC via SPI
2427
// TODO init DMA to transfer ADC data to memory buffer
2528
// TODO init timer to trigger PIO conversions at required frequency (check driver settings)
2629
// TDB: do we need config input to know which timer slice and channel to use? or can we pick automatically?
2730
// TODO start everything up
2831

32+
33+
float sck_hz = 20e6;
34+
PIO pio = pio0;
35+
int sm = pio_claim_unused_sm(pio0, false);
36+
if (sm < 0) { pio = pio1; sm = pio_claim_unused_sm(pio1, true); }
37+
38+
uint off = pio_add_program(pio, &bu79100g_parallel3_program);
39+
pio_sm_config c = bu79100g_parallel3_program_get_default_config(off);
40+
41+
// Map pins to the SM
42+
sm_config_set_in_pins(&c, this->pinD0); // reads D0..D2
43+
sm_config_set_set_pins(&c, this->pinCSB, 1); // CSB (1 pin)
44+
sm_config_set_sideset_pins(&c, this->pinSCK); // SCK (sideset)
45+
46+
// Put pins into PIO control
47+
pio_gpio_init(pio, this->pinSCK);
48+
pio_gpio_init(pio, this->pinCSB);
49+
pio_gpio_init(pio, this->pinD0);
50+
pio_gpio_init(pio, this->pinD1);
51+
pio_gpio_init(pio, this->pinD2);
52+
53+
// Directions (from the SM’s point of view)
54+
pio_sm_set_consecutive_pindirs(pio, sm, this->pinSCK, 1, true); // SCK out
55+
pio_sm_set_consecutive_pindirs(pio, sm, this->pinCSB, 1, true); // CS out
56+
pio_sm_set_consecutive_pindirs(pio, sm, this->pinD0, 3, false); // D0..D2 in
57+
58+
// Shift config: right, autopush every 24 bits (two pushes per conversion)
59+
sm_config_set_in_shift(&c, true, true, 24);
60+
61+
// SCK ≈ clk_sys / (2 * clkdiv) because each SCK period = 2 instructions
62+
float div = (float)clock_get_hz(clk_sys) / (2.0f * sck_hz);
63+
sm_config_set_clkdiv(&c, div);
64+
65+
// Init & start the SM
66+
pio_sm_init(pio, sm, off, &c);
67+
pio_sm_set_enabled(pio, sm, true);
68+
2969
return 0;
3070
};
3171

src/current/rp2350/RP2350PIOCurrentSense.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,25 @@
22
#pragma once
33

44
#include "common/base_classes/CurrentSense.h"
5-
5+
#include "bu79100g_parallel3.pio.h"
66

77
class RP2350PIOCurrentSense: public CurrentSense {
88
public:
9-
RP2350PIOCurrentSense(float gain, uint32_t max_adc_value, int pinA, int pinB, int pinC = _NC);
9+
RP2350PIOCurrentSense(float gain, uint32_t max_adc_value, int pinSCK, int pinCSB, int pinD0);
1010
~RP2350PIOCurrentSense();
1111

1212
int init() override;
1313

1414
PhaseCurrent_s getPhaseCurrents() override;
1515
protected:
1616
uint32_t max_adc_value; //!< maximum ADC value (e.g. 4096 for 12 bit ADC)
17+
int pinCSB;
18+
int pinSCK;
19+
int pinD0;
20+
int pinD1;
21+
int pinD2;
22+
int gain_a;
23+
int gain_b;
24+
int gain_c;
25+
1726
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.program bu79100g_parallel3
2+
; BU79100G-LA parallel read of 3 ADCs with a trigger GPIO
3+
; sideset pin: SCK (1 pin), CPOL=1 idle HIGH
4+
; set pin: CSB (1 pin)
5+
; in_base: D0..D2 (3 contiguous input pins)
6+
7+
.side_set 1 opt ; 1 sideset bit to drive SCK
8+
9+
.wrap_target
10+
set pins, 1 side 1 ; CSB=1, SCK=1
11+
; -------- wait external falling edge on absolute GPIO ----------
12+
wait 1 gpio 11 ; TODO, we will need to have this pin setable from the C code. direcetly edit the program?
13+
wait 0 gpio 11
14+
set pins, 0 side 1 ; CS=0, SCK=1
15+
set x, 15 side 1 ; prepare loop cpt
16+
; -------- 16 dummy clocks (no sampling) -----------------------
17+
dummy_loop:
18+
nop side 0 ; SCK=0
19+
jmp x--, dummy_loop side 1 ; SCK=1
20+
set pins, 1 side 1 ; CSB=0, keep SCK=HIGH at CSB falling (datasheet rec.)
21+
set x, 15 side 1
22+
set pins, 0
23+
; -------- 16 real clocks, sample on SCK rising edge -----------
24+
read_loop:
25+
nop side 1 ;DEBUG so we don't have to wait for autopush.
26+
;in pins, 3 side 1 ; SCK=1, sample D2..D0 on rising edge
27+
jmp x--, read_loop side 0 ; SCK=0
28+
; -------- finish conversion -----------------------------------
29+
set pins, 1 side 1 ; CSB=1, SCK=1
30+
.wrap
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// -------------------------------------------------- //
2+
// This file is autogenerated by pioasm; do not edit! //
3+
// -------------------------------------------------- //
4+
5+
#pragma once
6+
7+
#if !PICO_NO_HARDWARE
8+
#include "hardware/pio.h"
9+
#endif
10+
11+
// ------------------ //
12+
// bu79100g_parallel3 //
13+
// ------------------ //
14+
15+
#define bu79100g_parallel3_wrap_target 0
16+
#define bu79100g_parallel3_wrap 12
17+
#define bu79100g_parallel3_pio_version 1
18+
19+
static const uint16_t bu79100g_parallel3_program_instructions[] = {
20+
// .wrap_target
21+
0xf801, // 0: set pins, 1 side 1
22+
0x208b, // 1: wait 1 gpio, 11
23+
0x200b, // 2: wait 0 gpio, 11
24+
0xf800, // 3: set pins, 0 side 1
25+
0xf82f, // 4: set x, 15 side 1
26+
0xb042, // 5: nop side 0
27+
0x1845, // 6: jmp x--, 5 side 1
28+
0xf801, // 7: set pins, 1 side 1
29+
0xf82f, // 8: set x, 15 side 1
30+
0xe000, // 9: set pins, 0
31+
0xb842, // 10: nop side 1
32+
0x104a, // 11: jmp x--, 10 side 0
33+
0xf801, // 12: set pins, 1 side 1
34+
// .wrap
35+
};
36+
37+
#if !PICO_NO_HARDWARE
38+
static const struct pio_program bu79100g_parallel3_program = {
39+
.instructions = bu79100g_parallel3_program_instructions,
40+
.length = 13,
41+
.origin = -1,
42+
.pio_version = bu79100g_parallel3_pio_version,
43+
#if PICO_PIO_VERSION > 0
44+
.used_gpio_ranges = 0x1
45+
#endif
46+
};
47+
48+
static inline pio_sm_config bu79100g_parallel3_program_get_default_config(uint offset) {
49+
pio_sm_config c = pio_get_default_sm_config();
50+
sm_config_set_wrap(&c, offset + bu79100g_parallel3_wrap_target, offset + bu79100g_parallel3_wrap);
51+
sm_config_set_sideset(&c, 2, true, false);
52+
return c;
53+
}
54+
#endif
55+

0 commit comments

Comments
 (0)