Fix logic analyser for non-power-of-2 sample widths, and clean and comment.
This commit is contained in:
parent
6724968c8d
commit
475a726c0d
@ -14,10 +14,12 @@
|
|||||||
// frequency.
|
// frequency.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/pio.h"
|
#include "hardware/pio.h"
|
||||||
#include "hardware/dma.h"
|
#include "hardware/dma.h"
|
||||||
|
#include "hardware/structs/bus_ctrl.h"
|
||||||
|
|
||||||
// Some logic to analyse:
|
// Some logic to analyse:
|
||||||
#include "hardware/structs/pwm.h"
|
#include "hardware/structs/pwm.h"
|
||||||
@ -26,6 +28,15 @@ const uint CAPTURE_PIN_BASE = 16;
|
|||||||
const uint CAPTURE_PIN_COUNT = 2;
|
const uint CAPTURE_PIN_COUNT = 2;
|
||||||
const uint CAPTURE_N_SAMPLES = 96;
|
const uint CAPTURE_N_SAMPLES = 96;
|
||||||
|
|
||||||
|
static inline uint bits_packed_per_word(uint pin_count) {
|
||||||
|
// If the number of pins to be sampled divides the shift register size, we
|
||||||
|
// can use the full SR and FIFO width, and push when the input shift count
|
||||||
|
// exactly reaches 32. If not, we have to push earlier, so we use the FIFO
|
||||||
|
// a little less efficiently.
|
||||||
|
const uint SHIFT_REG_WIDTH = 32;
|
||||||
|
return SHIFT_REG_WIDTH - (SHIFT_REG_WIDTH % pin_count);
|
||||||
|
}
|
||||||
|
|
||||||
void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float div) {
|
void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float div) {
|
||||||
// Load a program to capture n pins. This is just a single `in pins, n`
|
// Load a program to capture n pins. This is just a single `in pins, n`
|
||||||
// instruction with a wrap.
|
// instruction with a wrap.
|
||||||
@ -43,7 +54,10 @@ void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float
|
|||||||
sm_config_set_in_pins(&c, pin_base);
|
sm_config_set_in_pins(&c, pin_base);
|
||||||
sm_config_set_wrap(&c, offset, offset);
|
sm_config_set_wrap(&c, offset, offset);
|
||||||
sm_config_set_clkdiv(&c, div);
|
sm_config_set_clkdiv(&c, div);
|
||||||
sm_config_set_in_shift(&c, true, true, 32);
|
// Note that we may push at a < 32 bit threshold if pin_count does not
|
||||||
|
// divide 32. We are using shift-to-right, so the sample data ends up
|
||||||
|
// left-justified in the FIFO in this case, with some zeroes at the LSBs.
|
||||||
|
sm_config_set_in_shift(&c, true, true, bits_packed_per_word(pin_count));
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
}
|
}
|
||||||
@ -74,12 +88,17 @@ void print_capture_buf(const uint32_t *buf, uint pin_base, uint pin_count, uint3
|
|||||||
// 00: __--__--__--__--__--__--
|
// 00: __--__--__--__--__--__--
|
||||||
// 01: ____----____----____----
|
// 01: ____----____----____----
|
||||||
printf("Capture:\n");
|
printf("Capture:\n");
|
||||||
|
// Each FIFO record may be only partially filled with bits, depending on
|
||||||
|
// whether pin_count is a factor of 32.
|
||||||
|
uint record_size_bits = bits_packed_per_word(pin_count);
|
||||||
for (int pin = 0; pin < pin_count; ++pin) {
|
for (int pin = 0; pin < pin_count; ++pin) {
|
||||||
printf("%02d: ", pin + pin_base);
|
printf("%02d: ", pin + pin_base);
|
||||||
for (int sample = 0; sample < n_samples; ++sample) {
|
for (int sample = 0; sample < n_samples; ++sample) {
|
||||||
uint bit_index = pin + sample * pin_count;
|
uint bit_index = pin + sample * pin_count;
|
||||||
bool level = !!(buf[bit_index / 32] & 1u << (bit_index % 32));
|
uint word_index = bit_index / record_size_bits;
|
||||||
printf(level ? "-" : "_");
|
// Data is left-justified in each FIFO entry, hence the (32 - record_size_bits) offset
|
||||||
|
uint word_mask = 1u << (bit_index % record_size_bits + 32 - record_size_bits);
|
||||||
|
printf(buf[word_index] & word_mask ? "-" : "_");
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@ -89,7 +108,19 @@ int main() {
|
|||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
printf("PIO logic analyser example\n");
|
printf("PIO logic analyser example\n");
|
||||||
|
|
||||||
uint32_t capture_buf[(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32];
|
// We're going to capture into a u32 buffer, for best DMA efficiency. Need
|
||||||
|
// to be careful of rounding in case the number of pins being sampled
|
||||||
|
// isn't a power of 2.
|
||||||
|
uint total_sample_bits = CAPTURE_N_SAMPLES * CAPTURE_PIN_COUNT;
|
||||||
|
total_sample_bits += bits_packed_per_word(CAPTURE_PIN_COUNT) - 1;
|
||||||
|
uint buf_size_words = total_sample_bits / bits_packed_per_word(CAPTURE_PIN_COUNT);
|
||||||
|
uint32_t *capture_buf = malloc(buf_size_words * sizeof(uint32_t));
|
||||||
|
hard_assert(capture_buf);
|
||||||
|
|
||||||
|
// Grant high bus priority to the DMA, so it can shove the processors out
|
||||||
|
// of the way. This should only be needed if you are pushing things up to
|
||||||
|
// >16bits/clk here, i.e. if you need to saturate the bus completely.
|
||||||
|
bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS;
|
||||||
|
|
||||||
PIO pio = pio0;
|
PIO pio = pio0;
|
||||||
uint sm = 0;
|
uint sm = 0;
|
||||||
@ -98,9 +129,7 @@ int main() {
|
|||||||
logic_analyser_init(pio, sm, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, 1.f);
|
logic_analyser_init(pio, sm, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, 1.f);
|
||||||
|
|
||||||
printf("Arming trigger\n");
|
printf("Arming trigger\n");
|
||||||
logic_analyser_arm(pio, sm, dma_chan, capture_buf, //;
|
logic_analyser_arm(pio, sm, dma_chan, capture_buf, buf_size_words, CAPTURE_PIN_BASE, true);
|
||||||
(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32,
|
|
||||||
CAPTURE_PIN_BASE, true);
|
|
||||||
|
|
||||||
printf("Starting PWM example\n");
|
printf("Starting PWM example\n");
|
||||||
// PWM example: -----------------------------------------------------------
|
// PWM example: -----------------------------------------------------------
|
||||||
@ -119,6 +148,8 @@ int main() {
|
|||||||
pwm_hw->slice[0].csr = PWM_CH0_CSR_EN_BITS;
|
pwm_hw->slice[0].csr = PWM_CH0_CSR_EN_BITS;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The logic analyser should have started capturing as soon as it saw the
|
||||||
|
// first transition. Wait until the last sample comes in from the DMA.
|
||||||
dma_channel_wait_for_finish_blocking(dma_chan);
|
dma_channel_wait_for_finish_blocking(dma_chan);
|
||||||
|
|
||||||
print_capture_buf(capture_buf, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, CAPTURE_N_SAMPLES);
|
print_capture_buf(capture_buf, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, CAPTURE_N_SAMPLES);
|
||||||
|
|||||||
Reference in New Issue
Block a user