1
1
;
2
- ; Copyright (c) 2021 pmarques-dev @ github
2
+ ; Copyright (c) 2021-2023 pmarques-dev @ github
3
3
;
4
4
; SPDX-License-Identifier: BSD-3-Clause
5
5
;
6
6
7
7
.program quadrature_encoder
8
8
9
- ; this code must be loaded into address 0, but at 29 instructions, it probably
10
- ; wouldn't be able to share space with other programs anyway
9
+ ; the code must be loaded at address 0, because it uses computed jumps
11
10
.origin 0
12
11
13
12
20
19
; keeps the current encoder count and is incremented / decremented according to
21
20
; the steps sampled
22
21
23
- ; writing any non zero value to the TX FIFO makes the state machine push the
24
- ; current count to RX FIFO between 6 to 18 clocks afterwards. The worst case
25
- ; sampling loop takes 14 cycles, so this program is able to read step rates up
26
- ; to sysclk / 14 (e.g., sysclk 125MHz, max step rate = 8.9 Msteps/sec)
27
-
22
+ ; the program keeps trying to write the current count to the RX FIFO without
23
+ ; blocking. To read the current count, the user code must drain the FIFO first
24
+ ; and wait for a fresh sample (takes ~4 SM cycles on average). The worst case
25
+ ; sampling loop takes 10 cycles, so this program is able to read step rates up
26
+ ; to sysclk / 10 (e.g., sysclk 125MHz, max step rate = 12.5 Msteps/sec)
28
27
29
28
; 00 state
30
29
JMP update ; read 00
@@ -60,41 +59,29 @@ decrement:
60
59
; this is where the main loop starts
61
60
.wrap_target
62
61
update:
63
- ; we start by checking the TX FIFO to see if the main code is asking for
64
- ; the current count after the PULL noblock, OSR will have either 0 if
65
- ; there was nothing or the value that was there
66
- SET X, 0
67
- PULL noblock
68
-
69
- ; since there are not many free registers, and PULL is done into OSR, we
70
- ; have to do some juggling to avoid losing the state information and
71
- ; still place the values where we need them
72
- MOV X, OSR
73
- MOV OSR, ISR
74
-
75
- ; the main code did not ask for the count, so just go to "sample_pins"
76
- JMP !X, sample_pins
77
-
78
- ; if it did ask for the count, then we push it
79
- MOV ISR, Y ; we trash ISR, but we already have a copy in OSR
80
- PUSH
62
+ MOV ISR, Y
63
+ PUSH noblock
81
64
82
65
sample_pins:
83
66
; we shift into ISR the last state of the 2 input pins (now in OSR) and
84
67
; the new state of the 2 pins, thus producing the 4 bit target for the
85
- ; computed jump into the correct action for this state
86
- MOV ISR, NULL
87
- IN OSR , 2
68
+ ; computed jump into the correct action for this state. Both the PUSH
69
+ ; above and the OUT below zero the other bits in ISR
70
+ OUT ISR , 2
88
71
IN PINS, 2
72
+
73
+ ; save the state in the OSR, so that we can use ISR for other purposes
74
+ MOV OSR, ISR
75
+ ; jump to the correct state machine action
89
76
MOV PC, ISR
90
77
91
78
; the PIO does not have a increment instruction, so to do that we do a
92
79
; negate, decrement, negate sequence
93
80
increment:
94
- MOV X, ! Y
95
- JMP X --, increment_cont
81
+ MOV Y, ~ Y
82
+ JMP Y --, increment_cont
96
83
increment_cont:
97
- MOV Y, !X
84
+ MOV Y, ~Y
98
85
.wrap ; the .wrap here avoids one jump instruction and saves a cycle too
99
86
100
87
@@ -106,16 +93,16 @@ increment_cont:
106
93
107
94
// max_step_rate is used to lower the clock of the state machine to save power
108
95
// if the application doesn't require a very high sampling rate. Passing zero
109
- // will set the clock to the maximum, which gives a max step rate of around
110
- // 8.9 Msteps/sec at 125MHz
96
+ // will set the clock to the maximum
111
97
112
- static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint offset, uint pin, int max_step_rate)
98
+ static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint pin, int max_step_rate)
113
99
{
114
100
pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false);
115
101
gpio_pull_up(pin);
116
102
gpio_pull_up(pin + 1);
117
103
118
- pio_sm_config c = quadrature_encoder_program_get_default_config(offset);
104
+ pio_sm_config c = quadrature_encoder_program_get_default_config(0);
105
+
119
106
sm_config_set_in_pins(&c, pin); // for WAIT, IN
120
107
sm_config_set_jmp_pin(&c, pin); // for JMP
121
108
// shift to left, autopull disabled
@@ -127,38 +114,28 @@ static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint offset
127
114
if (max_step_rate == 0) {
128
115
sm_config_set_clkdiv(&c, 1.0);
129
116
} else {
130
- // one state machine loop takes at most 14 cycles
131
- float div = (float)clock_get_hz(clk_sys) / (14 * max_step_rate);
117
+ // one state machine loop takes at most 10 cycles
118
+ float div = (float)clock_get_hz(clk_sys) / (10 * max_step_rate);
132
119
sm_config_set_clkdiv(&c, div);
133
120
}
134
121
135
- pio_sm_init(pio, sm, offset , &c);
122
+ pio_sm_init(pio, sm, 0 , &c);
136
123
pio_sm_set_enabled(pio, sm, true);
137
124
}
138
125
139
-
140
- // When requesting the current count we may have to wait a few cycles (average
141
- // ~11 sysclk cycles) for the state machine to reply. If we are reading multiple
142
- // encoders, we may request them all in one go and then fetch them all, thus
143
- // avoiding doing the wait multiple times. If we are reading just one encoder,
144
- // we can use the "get_count" function to request and wait
145
-
146
- static inline void quadrature_encoder_request_count(PIO pio, uint sm)
147
- {
148
- pio->txf[sm] = 1;
149
- }
150
-
151
- static inline int32_t quadrature_encoder_fetch_count(PIO pio, uint sm)
152
- {
153
- while (pio_sm_is_rx_fifo_empty(pio, sm))
154
- tight_loop_contents();
155
- return pio->rxf[sm];
156
- }
157
-
158
126
static inline int32_t quadrature_encoder_get_count(PIO pio, uint sm)
159
127
{
160
- quadrature_encoder_request_count(pio, sm);
161
- return quadrature_encoder_fetch_count(pio, sm);
128
+ uint ret;
129
+ int n;
130
+
131
+ // if the FIFO has N entries, we fetch them to drain the FIFO,
132
+ // plus one entry which will be guaranteed to not be stale
133
+ n = pio_sm_get_rx_fifo_level(pio, sm) + 1;
134
+ while (n > 0) {
135
+ ret = pio_sm_get_blocking(pio, sm);
136
+ n--;
137
+ }
138
+ return ret;
162
139
}
163
140
164
141
%}
0 commit comments