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
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 
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 
78 static inline uint _pio_major_instr_bits(uint instr) {
79  return instr & 0xe000u;
80 }
81 
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 
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 
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 
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 
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 
161 static inline uint pio_encode_jmp(uint addr) {
162  return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
163 }
164 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
static uint pio_encode_irq_wait(bool relative, uint irq)
Encode a IRQ WAIT instructionThis is the equivalent of IRQ WAIT <irq> <relative>
Definition: pio_instructions.h:435
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:146
static uint pio_encode_wait_irq(bool polarity, bool relative, uint irq)
Encode a WAIT for IRQ instructionThis is the equivalent of WAIT <polarity> IRQ <irq> <relative> ...
Definition: pio_instructions.h:300
static uint pio_encode_jmp_x_dec(uint addr)
Encode a conditional JMP if scratch X non-zero (and post-decrement X) instructionThis is the equivale...
Definition: pio_instructions.h:187
static uint pio_encode_push(bool if_full, bool block)
Encode a PUSH instructionThis is the equivalent of PUSH <if_full>, <block>
Definition: pio_instructions.h:345
static uint pio_encode_jmp_pin(uint addr)
Encode a conditional JMP if input pin high instructionThis is the equivalent of JMP PIN <addr> ...
Definition: pio_instructions.h:239
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:128
static uint pio_encode_jmp_x_ne_y(uint addr)
Encode a conditional JMP if scratch X not equal scratch Y instructionThis is the equivalent of JMP X!...
Definition: pio_instructions.h:226
static uint pio_encode_nop(void)
Encode a NOP instructionThis is the equivalent of NOP which is itself encoded as MOV y...
Definition: pio_instructions.h:476
static uint pio_encode_wait_gpio(bool polarity, uint gpio)
Encode a WAIT for GPIO pin instructionThis is the equivalent of WAIT <polarity> GPIO <gpio> ...
Definition: pio_instructions.h:271
static uint pio_encode_set(enum pio_src_dest dest, uint value)
Encode a SET instructionThis is the equivalent of SET <dest>, <value>
Definition: pio_instructions.h:463
static uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instruction with bit invertThis is the equivalent of MOV <dest>, ~<src> ...
Definition: pio_instructions.h:389
static uint pio_encode_irq_set(bool relative, uint irq)
Encode a IRQ SET instructionThis is the equivalent of IRQ SET <irq> <relative>
Definition: pio_instructions.h:421
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_jmp(uint addr)
Encode an unconditional JMP instructionThis is the equivalent of JMP <addr>
Definition: pio_instructions.h:161
static uint pio_encode_jmp_not_osre(uint addr)
Encode a conditional JMP if output shift register not empty instructionThis is the equivalent of JMP ...
Definition: pio_instructions.h:252
static uint pio_encode_jmp_y_dec(uint addr)
Encode a conditional JMP if scratch Y non-zero (and post-decrement Y) instructionThis is the equivale...
Definition: pio_instructions.h:213
static uint pio_encode_delay(uint cycles)
Encode just the delay slot bits of an instruction.
Definition: pio_instructions.h:110
static uint pio_encode_jmp_not_x(uint addr)
Encode a conditional JMP if scratch X zero instructionThis is the equivalent of JMP !X <addr> ...
Definition: pio_instructions.h:174
static uint pio_encode_out(enum pio_src_dest dest, uint count)
Encode an OUT instructionThis is the equivalent of OUT <src>, <count>
Definition: pio_instructions.h:330
static uint pio_encode_pull(bool if_empty, bool block)
Encode a PULL instructionThis is the equivalent of PULL <if_empty>, <block>
Definition: pio_instructions.h:359
static uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instruction with bit reverseThis is the equivalent of MOV <dest>, ::<src> ...
Definition: pio_instructions.h:405
static uint pio_encode_wait_pin(bool polarity, uint pin)
Encode a WAIT for pin instructionThis is the equivalent of WAIT <polarity> PIN <pin> ...
Definition: pio_instructions.h:285
static uint pio_encode_irq_clear(bool relative, uint irq)
Encode a IRQ CLEAR instructionThis is the equivalent of IRQ CLEAR <irq> <relative> ...
Definition: pio_instructions.h:449
static uint pio_encode_in(enum pio_src_dest src, uint count)
Encode an IN instructionThis is the equivalent of IN <src>, <count>
Definition: pio_instructions.h:315
static uint pio_encode_jmp_not_y(uint addr)
Encode a conditional JMP if scratch Y zero instructionThis is the equivalent of JMP !Y <addr> ...
Definition: pio_instructions.h:200
static uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src)
Encode a MOV instructionThis is the equivalent of MOV <dest>, <src>
Definition: pio_instructions.h:373