14
14
// frequency.
15
15
16
16
#include <stdio.h>
17
+ #include <stdlib.h>
17
18
18
19
#include "pico/stdlib.h"
19
20
#include "hardware/pio.h"
20
21
#include "hardware/dma.h"
22
+ #include "hardware/structs/bus_ctrl.h"
21
23
22
24
// Some logic to analyse:
23
25
#include "hardware/structs/pwm.h"
@@ -26,6 +28,15 @@ const uint CAPTURE_PIN_BASE = 16;
26
28
const uint CAPTURE_PIN_COUNT = 2 ;
27
29
const uint CAPTURE_N_SAMPLES = 96 ;
28
30
31
+ static inline uint bits_packed_per_word (uint pin_count ) {
32
+ // If the number of pins to be sampled divides the shift register size, we
33
+ // can use the full SR and FIFO width, and push when the input shift count
34
+ // exactly reaches 32. If not, we have to push earlier, so we use the FIFO
35
+ // a little less efficiently.
36
+ const uint SHIFT_REG_WIDTH = 32 ;
37
+ return SHIFT_REG_WIDTH - (SHIFT_REG_WIDTH % pin_count );
38
+ }
39
+
29
40
void logic_analyser_init (PIO pio , uint sm , uint pin_base , uint pin_count , float div ) {
30
41
// Load a program to capture n pins. This is just a single `in pins, n`
31
42
// instruction with a wrap.
@@ -43,7 +54,10 @@ void logic_analyser_init(PIO pio, uint sm, uint pin_base, uint pin_count, float
43
54
sm_config_set_in_pins (& c , pin_base );
44
55
sm_config_set_wrap (& c , offset , offset );
45
56
sm_config_set_clkdiv (& c , div );
46
- sm_config_set_in_shift (& c , true, true, 32 );
57
+ // Note that we may push at a < 32 bit threshold if pin_count does not
58
+ // divide 32. We are using shift-to-right, so the sample data ends up
59
+ // left-justified in the FIFO in this case, with some zeroes at the LSBs.
60
+ sm_config_set_in_shift (& c , true, true, bits_packed_per_word (pin_count ));
47
61
sm_config_set_fifo_join (& c , PIO_FIFO_JOIN_RX );
48
62
pio_sm_init (pio , sm , offset , & c );
49
63
}
@@ -74,12 +88,17 @@ void print_capture_buf(const uint32_t *buf, uint pin_base, uint pin_count, uint3
74
88
// 00: __--__--__--__--__--__--
75
89
// 01: ____----____----____----
76
90
printf ("Capture:\n" );
91
+ // Each FIFO record may be only partially filled with bits, depending on
92
+ // whether pin_count is a factor of 32.
93
+ uint record_size_bits = bits_packed_per_word (pin_count );
77
94
for (int pin = 0 ; pin < pin_count ; ++ pin ) {
78
95
printf ("%02d: " , pin + pin_base );
79
96
for (int sample = 0 ; sample < n_samples ; ++ sample ) {
80
97
uint bit_index = pin + sample * pin_count ;
81
- bool level = !!(buf [bit_index / 32 ] & 1u << (bit_index % 32 ));
82
- printf (level ? "-" : "_" );
98
+ uint word_index = bit_index / record_size_bits ;
99
+ // Data is left-justified in each FIFO entry, hence the (32 - record_size_bits) offset
100
+ uint word_mask = 1u << (bit_index % record_size_bits + 32 - record_size_bits );
101
+ printf (buf [word_index ] & word_mask ? "-" : "_" );
83
102
}
84
103
printf ("\n" );
85
104
}
@@ -89,7 +108,19 @@ int main() {
89
108
stdio_init_all ();
90
109
printf ("PIO logic analyser example\n" );
91
110
92
- uint32_t capture_buf [(CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31 ) / 32 ];
111
+ // We're going to capture into a u32 buffer, for best DMA efficiency. Need
112
+ // to be careful of rounding in case the number of pins being sampled
113
+ // isn't a power of 2.
114
+ uint total_sample_bits = CAPTURE_N_SAMPLES * CAPTURE_PIN_COUNT ;
115
+ total_sample_bits += bits_packed_per_word (CAPTURE_PIN_COUNT ) - 1 ;
116
+ uint buf_size_words = total_sample_bits / bits_packed_per_word (CAPTURE_PIN_COUNT );
117
+ uint32_t * capture_buf = malloc (buf_size_words * sizeof (uint32_t ));
118
+ hard_assert (capture_buf );
119
+
120
+ // Grant high bus priority to the DMA, so it can shove the processors out
121
+ // of the way. This should only be needed if you are pushing things up to
122
+ // >16bits/clk here, i.e. if you need to saturate the bus completely.
123
+ bus_ctrl_hw -> priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS ;
93
124
94
125
PIO pio = pio0 ;
95
126
uint sm = 0 ;
@@ -98,9 +129,7 @@ int main() {
98
129
logic_analyser_init (pio , sm , CAPTURE_PIN_BASE , CAPTURE_PIN_COUNT , 1.f );
99
130
100
131
printf ("Arming trigger\n" );
101
- logic_analyser_arm (pio , sm , dma_chan , capture_buf , //;
102
- (CAPTURE_PIN_COUNT * CAPTURE_N_SAMPLES + 31 ) / 32 ,
103
- CAPTURE_PIN_BASE , true);
132
+ logic_analyser_arm (pio , sm , dma_chan , capture_buf , buf_size_words , CAPTURE_PIN_BASE , true);
104
133
105
134
printf ("Starting PWM example\n" );
106
135
// PWM example: -----------------------------------------------------------
@@ -119,6 +148,8 @@ int main() {
119
148
pwm_hw -> slice [0 ].csr = PWM_CH0_CSR_EN_BITS ;
120
149
// ------------------------------------------------------------------------
121
150
151
+ // The logic analyser should have started capturing as soon as it saw the
152
+ // first transition. Wait until the last sample comes in from the DMA.
122
153
dma_channel_wait_for_finish_blocking (dma_chan );
123
154
124
155
print_capture_buf (capture_buf , CAPTURE_PIN_BASE , CAPTURE_PIN_COUNT , CAPTURE_N_SAMPLES );
0 commit comments