mirror of
https://github.com/clockworkpi/PicoCalc.git
synced 2025-12-12 10:18:54 +01:00
185 lines
6.9 KiB
C
185 lines
6.9 KiB
C
/*
|
|
* @cond
|
|
* The following section will be excluded from the documentation.
|
|
*/
|
|
/*
|
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#ifndef _HARDWARE_PIO_INSTRUCTIONS_H_
|
|
#define _HARDWARE_PIO_INSTRUCTIONS_H_
|
|
|
|
#include "pico.h"
|
|
|
|
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS, Enable/disable assertions in the PIO instructions, type=bool, default=0, group=hardware_pio
|
|
#ifndef PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
|
|
#define PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS 0
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
enum pio_instr_bits {
|
|
pio_instr_bits_jmp = 0x0000,
|
|
pio_instr_bits_wait = 0x2000,
|
|
pio_instr_bits_in = 0x4000,
|
|
pio_instr_bits_out = 0x6000,
|
|
pio_instr_bits_push = 0x8000,
|
|
pio_instr_bits_pull = 0x8080,
|
|
pio_instr_bits_mov = 0xa000,
|
|
pio_instr_bits_irq = 0xc000,
|
|
pio_instr_bits_set = 0xe000,
|
|
};
|
|
|
|
#ifndef NDEBUG
|
|
#define _PIO_INVALID_IN_SRC 0x08u
|
|
#define _PIO_INVALID_OUT_DEST 0x10u
|
|
#define _PIO_INVALID_SET_DEST 0x20u
|
|
#define _PIO_INVALID_MOV_SRC 0x40u
|
|
#define _PIO_INVALID_MOV_DEST 0x80u
|
|
#else
|
|
#define _PIO_INVALID_IN_SRC 0u
|
|
#define _PIO_INVALID_OUT_DEST 0u
|
|
#define _PIO_INVALID_SET_DEST 0u
|
|
#define _PIO_INVALID_MOV_SRC 0u
|
|
#define _PIO_INVALID_MOV_DEST 0u
|
|
#endif
|
|
|
|
enum pio_src_dest {
|
|
pio_pins = 0u,
|
|
pio_x = 1u,
|
|
pio_y = 2u,
|
|
pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
|
pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
|
|
pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
|
|
pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
|
pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
|
|
pio_isr = 6u | _PIO_INVALID_SET_DEST,
|
|
pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
|
|
pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
|
|
};
|
|
|
|
inline static uint _pio_major_instr_bits(uint instr) {
|
|
return instr & 0xe000u;
|
|
}
|
|
|
|
inline static uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
|
|
valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
|
|
#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
|
|
uint32_t major = _pio_major_instr_bits(instr_bits);
|
|
if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
|
|
assert(arg2 && arg2 <= 32);
|
|
} else {
|
|
assert(arg2 <= 31);
|
|
}
|
|
#endif
|
|
return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
|
|
}
|
|
|
|
inline static uint _pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits, enum pio_src_dest dest, uint value) {
|
|
return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
|
|
}
|
|
|
|
inline static uint pio_encode_delay(uint cycles) {
|
|
// note that the maximum cycles will be smaller if sideset_bit_count > 0
|
|
valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
|
|
return cycles << 8u;
|
|
}
|
|
|
|
inline static uint pio_encode_sideset(uint sideset_bit_count, uint value) {
|
|
valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 5);
|
|
valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
|
|
return value << (13u - sideset_bit_count);
|
|
}
|
|
|
|
inline static uint pio_encode_sideset_opt(uint sideset_bit_count, uint value) {
|
|
valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 4);
|
|
valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
|
|
return 0x1000u | value << (12u - sideset_bit_count);
|
|
}
|
|
|
|
inline static uint pio_encode_jmp(uint addr) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
|
|
}
|
|
|
|
inline static uint _pio_encode_irq(bool relative, uint irq) {
|
|
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
|
return (relative ? 0x10u : 0x0u) | irq;
|
|
}
|
|
|
|
inline static uint pio_encode_wait_gpio(bool polarity, uint pin) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 0u | (polarity ? 4u : 0u), pin);
|
|
}
|
|
|
|
inline static uint pio_encode_wait_pin(bool polarity, uint pin) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 1u | (polarity ? 4u : 0u), pin);
|
|
}
|
|
|
|
inline static uint pio_encode_wait_irq(bool polarity, bool relative, uint irq) {
|
|
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 2u | (polarity ? 4u : 0u), _pio_encode_irq(relative, irq));
|
|
}
|
|
|
|
inline static uint pio_encode_in(enum pio_src_dest src, uint value) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, value);
|
|
}
|
|
|
|
inline static uint pio_encode_out(enum pio_src_dest dest, uint value) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, value);
|
|
}
|
|
|
|
inline static uint pio_encode_push(bool if_full, bool block) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_push, (if_full ? 2u : 0u) | (block ? 1u : 0u), 0);
|
|
}
|
|
|
|
inline static uint pio_encode_pull(bool if_empty, bool block) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_pull, (if_empty ? 2u : 0u) | (block ? 1u : 0u), 0);
|
|
}
|
|
|
|
inline static uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
|
|
}
|
|
|
|
inline static uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (1u << 3u) | (src & 7u));
|
|
}
|
|
|
|
inline static uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (2u << 3u) | (src & 7u));
|
|
}
|
|
|
|
inline static uint pio_encode_irq_set(bool relative, uint irq) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_irq, 0, _pio_encode_irq(relative, irq));
|
|
}
|
|
|
|
inline static uint pio_encode_irq_clear(bool relative, uint irq) {
|
|
return _pio_encode_instr_and_args(pio_instr_bits_irq, 2, _pio_encode_irq(relative, irq));
|
|
}
|
|
|
|
inline static uint pio_encode_set(enum pio_src_dest dest, uint value) {
|
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
|
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
|
|
}
|
|
|
|
inline static uint pio_encode_nop(void) {
|
|
return pio_encode_mov(pio_y, pio_y);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
/* @endcond */
|