Initial Release
This commit is contained in:
125
pio/logic_analyser/logic_analyser.c
Normal file
125
pio/logic_analyser/logic_analyser.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
// PIO logic analyser example
|
||||
//
|
||||
// This program captures samples from a group of pins, at a fixed rate, once a
|
||||
// trigger condition is detected (level condition on one pin). The samples are
|
||||
// transferred to a capture buffer using the system DMA.
|
||||
//
|
||||
// 1 to 32 pins can be captured, at a sample rate no greater than system clock
|
||||
// frequency.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/pio.h"
|
||||
#include "hardware/dma.h"
|
||||
|
||||
// Some logic to analyse:
|
||||
#include "hardware/structs/pwm.h"
|
||||
|
||||
const uint CAPTURE_PIN_BASE = 16;
|
||||
const uint CAPTURE_PIN_COUNT = 2;
|
||||
const uint CAPTURE_N_SAMPLES = 96;
|
||||
|
||||
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`
|
||||
// instruction with a wrap.
|
||||
uint16_t capture_prog_instr = pio_encode_in(pio_pins, pin_count);
|
||||
struct pio_program capture_prog = {
|
||||
.instructions = &capture_prog_instr,
|
||||
.length = 1,
|
||||
.origin = -1
|
||||
};
|
||||
uint offset = pio_add_program(pio, &capture_prog);
|
||||
|
||||
// Configure state machine to loop over this `in` instruction forever,
|
||||
// with autopush enabled.
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_in_pins(&c, pin_base);
|
||||
sm_config_set_wrap(&c, offset, offset);
|
||||
sm_config_set_clkdiv(&c, div);
|
||||
sm_config_set_in_shift(&c, true, true, 32);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
}
|
||||
|
||||
void logic_analyser_arm(PIO pio, uint sm, uint dma_chan, uint32_t *capture_buf, size_t capture_size_words,
|
||||
uint trigger_pin, bool trigger_level) {
|
||||
pio_sm_set_enabled(pio, sm, false);
|
||||
pio_sm_clear_fifos(pio, sm);
|
||||
|
||||
dma_channel_config c = dma_channel_get_default_config(dma_chan);
|
||||
channel_config_set_read_increment(&c, false);
|
||||
channel_config_set_write_increment(&c, true);
|
||||
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false));
|
||||
|
||||
dma_channel_configure(dma_chan, &c,
|
||||
capture_buf, // Destinatinon pointer
|
||||
&pio->rxf[sm], // Source pointer
|
||||
capture_size_words, // Number of transfers
|
||||
true // Start immediately
|
||||
);
|
||||
|
||||
pio_sm_exec(pio, sm, pio_encode_wait_gpio(trigger_level, trigger_pin));
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
void print_capture_buf(const uint32_t *buf, uint pin_base, uint pin_count, uint32_t n_samples) {
|
||||
// Display the capture buffer in text form, like this:
|
||||
// 00: __--__--__--__--__--__--
|
||||
// 01: ____----____----____----
|
||||
printf("Capture:\n");
|
||||
for (int pin = 0; pin < pin_count; ++pin) {
|
||||
printf("%02d: ", pin + pin_base);
|
||||
for (int sample = 0; sample < n_samples; ++sample) {
|
||||
uint bit_index = pin + sample * pin_count;
|
||||
bool level = !!(buf[bit_index / 32] & 1u << (bit_index % 32));
|
||||
printf(level ? "-" : "_");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
printf("PIO logic analyser example\n");
|
||||
|
||||
uint32_t capture_buf[(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32];
|
||||
|
||||
PIO pio = pio0;
|
||||
uint sm = 0;
|
||||
uint dma_chan = 0;
|
||||
|
||||
logic_analyser_init(pio, sm, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, 1.f);
|
||||
|
||||
printf("Arming trigger\n");
|
||||
logic_analyser_arm(pio, sm, dma_chan, capture_buf, //;
|
||||
(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31) / 32,
|
||||
CAPTURE_PIN_BASE, true);
|
||||
|
||||
printf("Starting PWM example\n");
|
||||
// PWM example: -----------------------------------------------------------
|
||||
gpio_set_function(CAPTURE_PIN_BASE, GPIO_FUNC_PWM);
|
||||
gpio_set_function(CAPTURE_PIN_BASE + 1, GPIO_FUNC_PWM);
|
||||
// Topmost value of 3: count from 0 to 3 and then wrap, so period is 4 cycles
|
||||
pwm_hw->slice[0].top = 3;
|
||||
// Divide frequency by two to slow things down a little
|
||||
pwm_hw->slice[0].div = 4 << PWM_CH0_DIV_INT_LSB;
|
||||
// Set channel A to be high for 1 cycle each period (duty cycle 1/4) and
|
||||
// channel B for 3 cycles (duty cycle 3/4)
|
||||
pwm_hw->slice[0].cc =
|
||||
(1 << PWM_CH0_CC_A_LSB) |
|
||||
(3 << PWM_CH0_CC_B_LSB);
|
||||
// Enable this PWM slice
|
||||
pwm_hw->slice[0].csr = PWM_CH0_CSR_EN_BITS;
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
dma_channel_wait_for_finish_blocking(dma_chan);
|
||||
|
||||
print_capture_buf(capture_buf, CAPTURE_PIN_BASE, CAPTURE_PIN_COUNT, CAPTURE_N_SAMPLES);
|
||||
}
|
||||
Reference in New Issue
Block a user