Here it is with all three signals in "set pins", none in sideset, modulation (for example) set to 2:64 clocks.
None dithering.
The rundown part not tested yet as I do not have the analog part handy.
The runup timings of the PWMA, PWMB and MEAS look ok (on the first glance) on my scope.
29 instructions at this moment..
PS: the rundown result with the below code will be calculated (my current understanding, please confirm, my math gets rusty):
Result = 3 - 2*RDN + RDNP
where RDN and RDNP are the results returned by the PIO from the rundown.
Edit: small fix
.program ms
; MEAS PWMB PWMA signals in "set pins" with 4+2+1 weights
; don't forget to enable auto push
start:
set pins, (0+0) ; switch all off (not required perhaps)
mov X, !NULL ; set X to 0xFFFFFFFF
out Y, 32 ; read the number of desired counts
irq 0 ; first auxADC residue reading
out NULL, 32 ; stall until DMA finished reading the ADC
beginning:
set pins, (4+1) ; MEAS=1
jmp pin pwmhigh
set pins, (4+2) [31] ; was 15
jmp Y-- beginning [29] ; was 13
set pins, (0+2) ; MEAS=0
jmp finish
pwmhigh:
jmp X-- dummy [31] ; was 15
dummy:
nop [27] ; was 11
set pins, (4+2)
jmp Y-- beginning
set pins, (0+2) ; MEAS=0
jmp finish
finish:
in X, 32 ; send X to FIFO (runup-counts), ref to neg, input off
; rundown
mov X, !NULL ; set X to 0xFFFFFFFF
count_neg:
jmp pin end_neg
jmp X-- count_neg ; count, jump to close the loop
end_neg:
in X, 32 [2] ; send X to FIFO (counts for neg ref.), some delay for minimum pulse length for settling
set pins, (0+1)
count_pos:
jmp X-- cont ; count, no real jump
cont:
jmp pin count_pos
count_end:
set pins, (0+0) ; turn switches off
in X, 32 ; send X to FIFO (counts for neg+pos ref.)
irq 1 ; second auxADC residue reading
out NULL, 32 ; stall until DMA finished reading the ADC
% c-sdk {
// Helper function (for use in C program) to initialize this PIO program
void ms_program_init(PIO pio, uint sm, uint offset, uint pin, uint input, float div, uint pin_MEAS) {
// Sets up state machine and wrap target. This function is automatically
pio_sm_config c = ms_program_get_default_config(offset);
// Allow PIO to control GPIO pin (as output)
pio_gpio_init(pio, pin);
pio_gpio_init(pio, pin+1);
pio_gpio_init(pio, pin_MEAS);
// set the pin for jump if pin high instruction
sm_config_set_jmp_pin(&c, input);
// Connect pin to SET pin (control with 'set' instruction)
sm_config_set_set_pins(&c, pin, 3);
// Set the pin direction to output (in PIO)
pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, true); // 2 pins for PWM high and low
pio_sm_set_consecutive_pindirs(pio, sm, pin_MEAS, 1, true); // 1 pin for MEAS pin
// Set auto push to ISR
sm_config_set_in_shift(&c, false, true, 32);
sm_config_set_out_shift(&c, false, true, 32);
// Set the clock divider for the state machine
sm_config_set_clkdiv(&c, div);
// Load configuration and jump to start of the program
pio_sm_init(pio, sm, offset, &c);
}
%}
And the reading of the additional rundown results off the PIO's FIFO is easy (and it works):
void get_counts(PIO pio, uint sm , uint32_t countNum){
pio_sm_put_blocking(pio, sm, countNum - 1);
counts = ~pio_sm_get_blocking(pio, sm); // MS runup count
RDN = ~pio_sm_get_blocking(pio, sm); // rundown negative charge
RDNP = ~pio_sm_get_blocking(pio, sm); // rundown negative+positive charge
}