1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_PIO_INSTRUCTIONS_H
8 #define _HARDWARE_PIO_INSTRUCTIONS_H
9 
10 #include "pico.h"
11 
12 /** \brief PIO instruction encoding
13  *  \defgroup pio_instructions pio_instructions
14  *  \ingroup hardware_pio
15  *
16  * Functions for generating PIO instruction encodings programmatically. In debug builds
17  *`PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` can be set to 1 to enable validation of encoding function
18  * parameters.
19  *
20  * For fuller descriptions of the instructions in question see the "RP2040 Datasheet"
21  */
22 
23 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS, Enable/disable assertions in the PIO instructions, type=bool, default=0, group=pio_instructions
24 #ifndef PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
25 #define PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS 0
26 #endif
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 enum pio_instr_bits {
33     pio_instr_bits_jmp = 0x0000,
34     pio_instr_bits_wait = 0x2000,
35     pio_instr_bits_in = 0x4000,
36     pio_instr_bits_out = 0x6000,
37     pio_instr_bits_push = 0x8000,
38     pio_instr_bits_pull = 0x8080,
39     pio_instr_bits_mov = 0xa000,
40     pio_instr_bits_irq = 0xc000,
41     pio_instr_bits_set = 0xe000,
42 };
43 
44 #ifndef NDEBUG
45 #define _PIO_INVALID_IN_SRC    0x08u
46 #define _PIO_INVALID_OUT_DEST 0x10u
47 #define _PIO_INVALID_SET_DEST 0x20u
48 #define _PIO_INVALID_MOV_SRC  0x40u
49 #define _PIO_INVALID_MOV_DEST 0x80u
50 #else
51 #define _PIO_INVALID_IN_SRC    0u
52 #define _PIO_INVALID_OUT_DEST 0u
53 #define _PIO_INVALID_SET_DEST 0u
54 #define _PIO_INVALID_MOV_SRC  0u
55 #define _PIO_INVALID_MOV_DEST 0u
56 #endif
57 
58 /*! \brief Enumeration of values to pass for source/destination args for instruction encoding functions
59  *  \ingroup pio_instructions
60  *
61  * \note Not all values are suitable for all functions. Validity is only checked in debug mode when
62  * `PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` is 1
63  */
64 enum pio_src_dest {
65     pio_pins = 0u,
66     pio_x = 1u,
67     pio_y = 2u,
68     pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
69     pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
70     pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
71     pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
72     pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
73     pio_isr = 6u | _PIO_INVALID_SET_DEST,
74     pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
75     pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
76 };
77 
_pio_major_instr_bits(uint instr)78 static inline uint _pio_major_instr_bits(uint instr) {
79     return instr & 0xe000u;
80 }
81 
_pio_encode_instr_and_args(enum pio_instr_bits instr_bits,uint arg1,uint arg2)82 static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
83     valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
84 #if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
85     uint32_t major = _pio_major_instr_bits(instr_bits);
86     if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
87         assert(arg2 && arg2 <= 32);
88     } else {
89         assert(arg2 <= 31);
90     }
91 #endif
92     return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
93 }
94 
_pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits,enum pio_src_dest dest,uint value)95 static inline uint _pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits, enum pio_src_dest dest, uint value) {
96     return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
97 }
98 
99 /*! \brief Encode just the delay slot bits of an instruction
100  *  \ingroup pio_instructions
101  *
102  * \note This function does not return a valid instruction encoding; instead it returns an encoding of the delay
103  * slot suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
104  * combining the results of this function with the results of \ref pio_encode_sideset and \ref pio_encode_sideset_opt
105  * as they share the same bits within the instruction encoding.
106  *
107  * \param cycles the number of cycles 0-31 (or less if side set is being used)
108  * \return the delay slot bits to be ORed with an instruction encoding
109  */
pio_encode_delay(uint cycles)110 static inline uint pio_encode_delay(uint cycles) {
111     // note that the maximum cycles will be smaller if sideset_bit_count > 0
112     valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
113     return cycles << 8u;
114 }
115 
116 /*! \brief Encode just the side set bits of an instruction (in non optional side set mode)
117  *  \ingroup pio_instructions
118  *
119  * \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
120  * suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
121  * combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
122  * within the instruction encoding.
123  *
124  * \param sideset_bit_count number of side set bits as would be specified via `.sideset` in pioasm
125  * \param value the value to sideset on the pins
126  * \return the side set bits to be ORed with an instruction encoding
127  */
pio_encode_sideset(uint sideset_bit_count,uint value)128 static inline uint pio_encode_sideset(uint sideset_bit_count, uint value) {
129     valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 5);
130     valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
131     return value << (13u - sideset_bit_count);
132 }
133 
134 /*! \brief Encode just the side set bits of an instruction (in optional -`opt` side set mode)
135  *  \ingroup pio_instructions
136  *
137  * \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
138  * suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
139  * combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
140  * within the instruction encoding.
141  *
142  * \param sideset_bit_count number of side set bits as would be specified via `.sideset <n> opt` in pioasm
143  * \param value the value to sideset on the pins
144  * \return the side set bits to be ORed with an instruction encoding
145  */
pio_encode_sideset_opt(uint sideset_bit_count,uint value)146 static inline uint pio_encode_sideset_opt(uint sideset_bit_count, uint value) {
147     valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 4);
148     valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
149     return 0x1000u | value << (12u - sideset_bit_count);
150 }
151 
152 /*! \brief Encode an unconditional JMP instruction
153  *  \ingroup pio_instructions
154  *
155  * This is the equivalent of `JMP <addr>`
156  *
157  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
158  * \return The instruction encoding with 0 delay and no side set value
159  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
160  */
pio_encode_jmp(uint addr)161 static inline uint pio_encode_jmp(uint addr) {
162     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
163 }
164 
165 /*! \brief Encode a conditional JMP if scratch X zero instruction
166  *  \ingroup pio_instructions
167  *
168  * This is the equivalent of `JMP !X <addr>`
169  *
170  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
171  * \return The instruction encoding with 0 delay and no side set value
172  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
173  */
pio_encode_jmp_not_x(uint addr)174 static inline uint pio_encode_jmp_not_x(uint addr) {
175     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 1, addr);
176 }
177 
178 /*! \brief Encode a conditional JMP if scratch X non-zero (and post-decrement X) instruction
179  *  \ingroup pio_instructions
180  *
181  * This is the equivalent of `JMP X-- <addr>`
182  *
183  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
184  * \return The instruction encoding with 0 delay and no side set value
185  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
186  */
pio_encode_jmp_x_dec(uint addr)187 static inline uint pio_encode_jmp_x_dec(uint addr) {
188     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 2, addr);
189 }
190 
191 /*! \brief Encode a conditional JMP if scratch Y zero instruction
192  *  \ingroup pio_instructions
193  *
194  * This is the equivalent of `JMP !Y <addr>`
195  *
196  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
197  * \return The instruction encoding with 0 delay and no side set value
198  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
199  */
pio_encode_jmp_not_y(uint addr)200 static inline uint pio_encode_jmp_not_y(uint addr) {
201     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 3, addr);
202 }
203 
204 /*! \brief Encode a conditional JMP if scratch Y non-zero (and post-decrement Y) instruction
205  *  \ingroup pio_instructions
206  *
207  * This is the equivalent of `JMP Y-- <addr>`
208  *
209  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
210  * \return The instruction encoding with 0 delay and no side set value
211  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
212  */
pio_encode_jmp_y_dec(uint addr)213 static inline uint pio_encode_jmp_y_dec(uint addr) {
214     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 4, addr);
215 }
216 
217 /*! \brief Encode a conditional JMP if scratch X not equal scratch Y instruction
218  *  \ingroup pio_instructions
219  *
220  * This is the equivalent of `JMP X!=Y <addr>`
221  *
222  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
223  * \return The instruction encoding with 0 delay and no side set value
224  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
225  */
pio_encode_jmp_x_ne_y(uint addr)226 static inline uint pio_encode_jmp_x_ne_y(uint addr) {
227     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 5, addr);
228 }
229 
230 /*! \brief Encode a conditional JMP if input pin high instruction
231  *  \ingroup pio_instructions
232  *
233  * This is the equivalent of `JMP PIN <addr>`
234  *
235  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
236  * \return The instruction encoding with 0 delay and no side set value
237  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
238  */
pio_encode_jmp_pin(uint addr)239 static inline uint pio_encode_jmp_pin(uint addr) {
240     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 6, addr);
241 }
242 
243 /*! \brief Encode a conditional JMP if output shift register not empty instruction
244  *  \ingroup pio_instructions
245  *
246  * This is the equivalent of `JMP !OSRE <addr>`
247  *
248  * \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
249  * \return The instruction encoding with 0 delay and no side set value
250  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
251  */
pio_encode_jmp_not_osre(uint addr)252 static inline uint pio_encode_jmp_not_osre(uint addr) {
253     return _pio_encode_instr_and_args(pio_instr_bits_jmp, 7, addr);
254 }
255 
_pio_encode_irq(bool relative,uint irq)256 static inline uint _pio_encode_irq(bool relative, uint irq) {
257     valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
258     return (relative ? 0x10u : 0x0u) | irq;
259 }
260 
261 /*! \brief Encode a WAIT for GPIO pin instruction
262  *  \ingroup pio_instructions
263  *
264  * This is the equivalent of `WAIT <polarity> GPIO <gpio>`
265  *
266  * \param polarity true for `WAIT 1`, false for `WAIT 0`
267  * \param gpio The real GPIO number 0-31
268  * \return The instruction encoding with 0 delay and no side set value
269  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
270  */
pio_encode_wait_gpio(bool polarity,uint gpio)271 static inline uint pio_encode_wait_gpio(bool polarity, uint gpio) {
272     return _pio_encode_instr_and_args(pio_instr_bits_wait, 0u | (polarity ? 4u : 0u), gpio);
273 }
274 
275 /*! \brief Encode a WAIT for pin instruction
276  *  \ingroup pio_instructions
277  *
278  * This is the equivalent of `WAIT <polarity> PIN <pin>`
279  *
280  * \param polarity true for `WAIT 1`, false for `WAIT 0`
281  * \param pin The pin number 0-31 relative to the executing SM's input pin mapping
282  * \return The instruction encoding with 0 delay and no side set value
283  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
284  */
pio_encode_wait_pin(bool polarity,uint pin)285 static inline uint pio_encode_wait_pin(bool polarity, uint pin) {
286     return _pio_encode_instr_and_args(pio_instr_bits_wait, 1u | (polarity ? 4u : 0u), pin);
287 }
288 
289 /*! \brief Encode a WAIT for IRQ instruction
290  *  \ingroup pio_instructions
291  *
292  * This is the equivalent of `WAIT <polarity> IRQ <irq> <relative>`
293  *
294  * \param polarity true for `WAIT 1`, false for `WAIT 0`
295  * \param relative true for a `WAIT IRQ <irq> REL`, false for regular `WAIT IRQ <irq>`
296  * \param irq the irq number 0-7
297  * \return The instruction encoding with 0 delay and no side set value
298  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
299  */
pio_encode_wait_irq(bool polarity,bool relative,uint irq)300 static inline uint pio_encode_wait_irq(bool polarity, bool relative, uint irq) {
301     valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
302     return _pio_encode_instr_and_args(pio_instr_bits_wait, 2u | (polarity ? 4u : 0u), _pio_encode_irq(relative, irq));
303 }
304 
305 /*! \brief Encode an IN instruction
306  *  \ingroup pio_instructions
307  *
308  * This is the equivalent of `IN <src>, <count>`
309  *
310  * \param src The source to take data from
311  * \param count The number of bits 1-32
312  * \return The instruction encoding with 0 delay and no side set value
313  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
314  */
pio_encode_in(enum pio_src_dest src,uint count)315 static inline uint pio_encode_in(enum pio_src_dest src, uint count) {
316     valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
317     return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, count);
318 }
319 
320 /*! \brief Encode an OUT instruction
321  *  \ingroup pio_instructions
322  *
323  * This is the equivalent of `OUT <src>, <count>`
324  *
325  * \param dest The destination to write data to
326  * \param count The number of bits 1-32
327  * \return The instruction encoding with 0 delay and no side set value
328  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
329  */
pio_encode_out(enum pio_src_dest dest,uint count)330 static inline uint pio_encode_out(enum pio_src_dest dest, uint count) {
331     valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
332     return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, count);
333 }
334 
335 /*! \brief Encode a PUSH instruction
336  *  \ingroup pio_instructions
337  *
338  * This is the equivalent of `PUSH <if_full>, <block>`
339  *
340  * \param if_full true for `PUSH IF_FULL ...`, false for `PUSH ...`
341  * \param block true for `PUSH ... BLOCK`, false for `PUSH ...`
342  * \return The instruction encoding with 0 delay and no side set value
343  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
344  */
pio_encode_push(bool if_full,bool block)345 static inline uint pio_encode_push(bool if_full, bool block) {
346     return _pio_encode_instr_and_args(pio_instr_bits_push, (if_full ? 2u : 0u) | (block ? 1u : 0u), 0);
347 }
348 
349 /*! \brief Encode a PULL instruction
350  *  \ingroup pio_instructions
351  *
352  * This is the equivalent of `PULL <if_empty>, <block>`
353  *
354  * \param if_empty true for `PULL IF_EMPTY ...`, false for `PULL ...`
355  * \param block true for `PULL ... BLOCK`, false for `PULL ...`
356  * \return The instruction encoding with 0 delay and no side set value
357  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
358  */
pio_encode_pull(bool if_empty,bool block)359 static inline uint pio_encode_pull(bool if_empty, bool block) {
360     return _pio_encode_instr_and_args(pio_instr_bits_pull, (if_empty ? 2u : 0u) | (block ? 1u : 0u), 0);
361 }
362 
363 /*! \brief Encode a MOV instruction
364  *  \ingroup pio_instructions
365  *
366  * This is the equivalent of `MOV <dest>, <src>`
367  *
368  * \param dest The destination to write data to
369  * \param src The source to take data from
370  * \return The instruction encoding with 0 delay and no side set value
371  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
372  */
pio_encode_mov(enum pio_src_dest dest,enum pio_src_dest src)373 static inline uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) {
374     valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
375     valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
376     return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
377 }
378 
379 /*! \brief Encode a MOV instruction with bit invert
380  *  \ingroup pio_instructions
381  *
382  * This is the equivalent of `MOV <dest>, ~<src>`
383  *
384  * \param dest The destination to write inverted data to
385  * \param src The source to take data from
386  * \return The instruction encoding with 0 delay and no side set value
387  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
388  */
pio_encode_mov_not(enum pio_src_dest dest,enum pio_src_dest src)389 static inline uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src) {
390     valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
391     valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
392     return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (1u << 3u) | (src & 7u));
393 }
394 
395 /*! \brief Encode a MOV instruction with bit reverse
396  *  \ingroup pio_instructions
397  *
398  * This is the equivalent of `MOV <dest>, ::<src>`
399  *
400  * \param dest The destination to write bit reversed data to
401  * \param src The source to take data from
402  * \return The instruction encoding with 0 delay and no side set value
403  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
404  */
pio_encode_mov_reverse(enum pio_src_dest dest,enum pio_src_dest src)405 static inline uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src) {
406     valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
407     valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
408     return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (2u << 3u) | (src & 7u));
409 }
410 
411 /*! \brief Encode a IRQ SET instruction
412  *  \ingroup pio_instructions
413  *
414  * This is the equivalent of `IRQ SET <irq> <relative>`
415  *
416  * \param relative true for a `IRQ SET <irq> REL`, false for regular `IRQ SET <irq>`
417  * \param irq the irq number 0-7
418  * \return The instruction encoding with 0 delay and no side set value
419  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
420  */
pio_encode_irq_set(bool relative,uint irq)421 static inline uint pio_encode_irq_set(bool relative, uint irq) {
422     return _pio_encode_instr_and_args(pio_instr_bits_irq, 0, _pio_encode_irq(relative, irq));
423 }
424 
425 /*! \brief Encode a IRQ WAIT instruction
426  *  \ingroup pio_instructions
427  *
428  * This is the equivalent of `IRQ WAIT <irq> <relative>`
429  *
430  * \param relative true for a `IRQ WAIT <irq> REL`, false for regular `IRQ WAIT <irq>`
431  * \param irq the irq number 0-7
432  * \return The instruction encoding with 0 delay and no side set value
433  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
434  */
pio_encode_irq_wait(bool relative,uint irq)435 static inline uint pio_encode_irq_wait(bool relative, uint irq) {
436     return _pio_encode_instr_and_args(pio_instr_bits_irq, 1, _pio_encode_irq(relative, irq));
437 }
438 
439 /*! \brief Encode a IRQ CLEAR instruction
440  *  \ingroup pio_instructions
441  *
442  * This is the equivalent of `IRQ CLEAR <irq> <relative>`
443  *
444  * \param relative true for a `IRQ CLEAR <irq> REL`, false for regular `IRQ CLEAR <irq>`
445  * \param irq the irq number 0-7
446  * \return The instruction encoding with 0 delay and no side set value
447  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
448  */
pio_encode_irq_clear(bool relative,uint irq)449 static inline uint pio_encode_irq_clear(bool relative, uint irq) {
450     return _pio_encode_instr_and_args(pio_instr_bits_irq, 2, _pio_encode_irq(relative, irq));
451 }
452 
453 /*! \brief Encode a SET instruction
454  *  \ingroup pio_instructions
455  *
456  * This is the equivalent of `SET <dest>, <value>`
457  *
458  * \param dest The destination to apply the value to
459  * \param value The value 0-31
460  * \return The instruction encoding with 0 delay and no side set value
461  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
462  */
pio_encode_set(enum pio_src_dest dest,uint value)463 static inline uint pio_encode_set(enum pio_src_dest dest, uint value) {
464     valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
465     return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
466 }
467 
468 /*! \brief Encode a NOP instruction
469  *  \ingroup pio_instructions
470  *
471  * This is the equivalent of `NOP` which is itself encoded as `MOV y, y`
472  *
473  * \return The instruction encoding with 0 delay and no side set value
474  * \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
475  */
pio_encode_nop(void)476 static inline uint pio_encode_nop(void) {
477     return pio_encode_mov(pio_y, pio_y);
478 }
479 
480 #ifdef __cplusplus
481 }
482 #endif
483 
484 #endif
485