Loading...
Searching...
No Matches
pio_instructions.h
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
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
29extern "C" {
30#endif
31
32enum 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
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#if PICO_PIO_VERSION > 0
70 pio_pindirs_mov = 3u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC,
71 pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC,
72#else
73 pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
74#endif
75 pio_pindirs_out = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
76 pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
77 pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
78 pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
79 pio_isr = 6u | _PIO_INVALID_SET_DEST,
80 pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
81 pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
82 pio_exec = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
83};
84
85static inline uint _pio_major_instr_bits(uint instr) {
86 return instr & 0xe000u;
87}
88
89static inline uint _pio_arg1(uint instr) {
90 return (instr >> 5) & 0x7u;
91}
92
93static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
94 valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
95#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
96 uint32_t major = _pio_major_instr_bits(instr_bits);
97 if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
98 assert(arg2 && arg2 <= 32);
99 } else {
100 assert(arg2 <= 31);
101 }
102#endif
103 return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
104}
105
106static inline uint _pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits, enum pio_src_dest dest, uint value) {
107 return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
108}
109
121static inline uint pio_encode_delay(uint cycles) {
122 // note that the maximum cycles will be smaller if sideset_bit_count > 0
123 valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
124 return cycles << 8u;
125}
126
139static inline uint pio_encode_sideset(uint sideset_bit_count, uint value) {
140 valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 5);
141 valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
142 return value << (13u - sideset_bit_count);
143}
144
157static inline uint pio_encode_sideset_opt(uint sideset_bit_count, uint value) {
158 valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count <= 4);
159 valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
160 return 0x1000u | value << (12u - sideset_bit_count);
161}
162
172static inline uint pio_encode_jmp(uint addr) {
173 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
174}
175
185static inline uint pio_encode_jmp_not_x(uint addr) {
186 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 1, addr);
187}
188
198static inline uint pio_encode_jmp_x_dec(uint addr) {
199 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 2, addr);
200}
201
211static inline uint pio_encode_jmp_not_y(uint addr) {
212 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 3, addr);
213}
214
224static inline uint pio_encode_jmp_y_dec(uint addr) {
225 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 4, addr);
226}
227
237static inline uint pio_encode_jmp_x_ne_y(uint addr) {
238 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 5, addr);
239}
240
250static inline uint pio_encode_jmp_pin(uint addr) {
251 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 6, addr);
252}
253
263static inline uint pio_encode_jmp_not_osre(uint addr) {
264 return _pio_encode_instr_and_args(pio_instr_bits_jmp, 7, addr);
265}
266
267static inline uint _pio_encode_irq(bool relative, uint irq) {
268 valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
269 return (relative ? 0x10u : 0x0u) | irq;
270}
271
286static inline uint pio_encode_wait_gpio(bool polarity, uint gpio) {
287 return _pio_encode_instr_and_args(pio_instr_bits_wait, 0u | (polarity ? 4u : 0u), gpio);
288}
289
300static inline uint pio_encode_wait_pin(bool polarity, uint pin) {
301 return _pio_encode_instr_and_args(pio_instr_bits_wait, 1u | (polarity ? 4u : 0u), pin);
302}
303
315static inline uint pio_encode_wait_irq(bool polarity, bool relative, uint irq) {
316 valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
317 return _pio_encode_instr_and_args(pio_instr_bits_wait, 2u | (polarity ? 4u : 0u), _pio_encode_irq(relative, irq));
318}
319
320#if PICO_PIO_VERSION > 0
331static inline uint pio_encode_wait_jmppin(bool polarity, uint offset) {
332 valid_params_if(PIO_INSTRUCTIONS, offset <= 4);
333 return _pio_encode_instr_and_args(pio_instr_bits_wait, 3u | (polarity ? 4u : 0u), offset);
334}
335#endif
336
347static inline uint pio_encode_in(enum pio_src_dest src, uint count) {
348 valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
349 return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, count);
350}
351
362static inline uint pio_encode_out(enum pio_src_dest dest, uint count) {
363 valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
364 static_assert((pio_pindirs & 7) == (pio_pindirs_out & 7), ""); // no need to convert
365 static_assert((pio_exec & 7) == (pio_exec_out & 7), ""); // no need to convert
366 return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, count);
367}
368
379static inline uint pio_encode_push(bool if_full, bool block) {
380 return _pio_encode_instr_and_args(pio_instr_bits_push, (if_full ? 2u : 0u) | (block ? 1u : 0u), 0);
381}
382
393static inline uint pio_encode_pull(bool if_empty, bool block) {
394 return _pio_encode_instr_and_args(pio_instr_bits_pull, (if_empty ? 2u : 0u) | (block ? 1u : 0u), 0);
395}
396
407static inline uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) {
408 valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
409 valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
410 // generic constants aren't the same as the MOV ones
411 if (dest == pio_exec) dest = pio_exec_mov;
412#if PICO_PIO_VERSION > 0
413 if (dest == pio_pindirs) dest = pio_pindirs_mov;
414#endif
415 return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
416}
417
428static inline uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src) {
429 valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
430 valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
431 return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (1u << 3u) | (src & 7u));
432}
433
444static inline uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src) {
445 valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
446 valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
447 return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (2u << 3u) | (src & 7u));
448}
449
460static inline uint pio_encode_irq_set(bool relative, uint irq) {
461 return _pio_encode_instr_and_args(pio_instr_bits_irq, 0, _pio_encode_irq(relative, irq));
462}
463
474static inline uint pio_encode_irq_wait(bool relative, uint irq) {
475 return _pio_encode_instr_and_args(pio_instr_bits_irq, 1, _pio_encode_irq(relative, irq));
476}
477
488static inline uint pio_encode_irq_clear(bool relative, uint irq) {
489 return _pio_encode_instr_and_args(pio_instr_bits_irq, 2, _pio_encode_irq(relative, irq));
490}
491
502static inline uint pio_encode_set(enum pio_src_dest dest, uint value) {
503 valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
504 return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
505}
506
515static inline uint pio_encode_nop(void) {
516 return pio_encode_mov(pio_y, pio_y);
517}
518
519#ifdef __cplusplus
520}
521#endif
522
523#endif
static uint pio_encode_jmp(uint addr)
Encode an unconditional JMP instruction.
Definition pio_instructions.h:172
static uint pio_encode_delay(uint cycles)
Encode just the delay slot bits of an instruction.
Definition pio_instructions.h:121
static uint pio_encode_irq_set(bool relative, uint irq)
Encode a IRQ SET instruction.
Definition pio_instructions.h:460
static uint pio_encode_wait_irq(bool polarity, bool relative, uint irq)
Encode a WAIT for IRQ instruction.
Definition pio_instructions.h:315
static uint pio_encode_push(bool if_full, bool block)
Encode a PUSH instruction.
Definition pio_instructions.h:379
static uint pio_encode_wait_gpio(bool polarity, uint gpio)
Encode a WAIT for GPIO pin instruction.
Definition pio_instructions.h:286
static uint pio_encode_sideset_opt(uint sideset_bit_count, uint value)
Encode just the side set bits of an instruction (in optional -opt side set mode)
Definition pio_instructions.h:157
pio_src_dest
Enumeration of values to pass for source/destination args for instruction encoding functions.
Definition pio_instructions.h:64
static uint pio_encode_irq_clear(bool relative, uint irq)
Encode a IRQ CLEAR instruction.
Definition pio_instructions.h:488
static uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instruction with bit invert.
Definition pio_instructions.h:428
static uint pio_encode_jmp_not_x(uint addr)
Encode a conditional JMP if scratch X zero instruction.
Definition pio_instructions.h:185
static uint pio_encode_pull(bool if_empty, bool block)
Encode a PULL instruction.
Definition pio_instructions.h:393
static uint pio_encode_out(enum pio_src_dest dest, uint count)
Encode an OUT instruction.
Definition pio_instructions.h:362
static uint pio_encode_jmp_y_dec(uint addr)
Encode a conditional JMP if scratch Y non-zero (and post-decrement Y) instruction.
Definition pio_instructions.h:224
static uint pio_encode_jmp_x_ne_y(uint addr)
Encode a conditional JMP if scratch X not equal scratch Y instruction.
Definition pio_instructions.h:237
static uint pio_encode_nop(void)
Encode a NOP instruction.
Definition pio_instructions.h:515
static uint pio_encode_in(enum pio_src_dest src, uint count)
Encode an IN instruction.
Definition pio_instructions.h:347
static uint pio_encode_jmp_pin(uint addr)
Encode a conditional JMP if input pin high instruction.
Definition pio_instructions.h:250
static uint pio_encode_sideset(uint sideset_bit_count, uint value)
Encode just the side set bits of an instruction (in non optional side set mode)
Definition pio_instructions.h:139
static uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instruction with bit reverse.
Definition pio_instructions.h:444
static uint pio_encode_jmp_x_dec(uint addr)
Encode a conditional JMP if scratch X non-zero (and post-decrement X) instruction.
Definition pio_instructions.h:198
static uint pio_encode_jmp_not_y(uint addr)
Encode a conditional JMP if scratch Y zero instruction.
Definition pio_instructions.h:211
static uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instruction.
Definition pio_instructions.h:407
static uint pio_encode_set(enum pio_src_dest dest, uint value)
Encode a SET instruction.
Definition pio_instructions.h:502
static uint pio_encode_irq_wait(bool relative, uint irq)
Encode a IRQ WAIT instruction.
Definition pio_instructions.h:474
static uint pio_encode_jmp_not_osre(uint addr)
Encode a conditional JMP if output shift register not empty instruction.
Definition pio_instructions.h:263
static uint pio_encode_wait_pin(bool polarity, uint pin)
Encode a WAIT for pin instruction.
Definition pio_instructions.h:300