26 #include "hardware/dma.h"
27 #include "hardware/gpio.h"
28 #include "hardware/irq.h"
29 #include "hardware/pio.h"
30 #include "hardware/pio_instructions.h"
31 #include "hardware/regs/intctrl.h"
32 #include "hardware/regs/pio.h"
33 #include "hardware/structs/dma.h"
34 #include "hardware/timer.h"
35 #include "pico/platform.h"
36 #include "pico/time.h"
37 #include "pico/types.h"
38 #include "../include/util.h"
40 #define UTIL_DEF_IN_RANGE_FUNC(TYPE) \
41 bool util_ ## TYPE ##_in_range( \
45 return val >= min && val <= max; \
66 return util_uint_in_range(
80 check_irq_param(irq_num);
97 const irq_handler_t handler,
101 check_dma_channel_param(channel);
102 assert(handler != NULL);
106 dma_irqn_set_channel_enabled(
111 irq_set_exclusive_handler(
122 check_dma_channel_param(channel);
123 return (uint32_t)dma_hw->ch[channel].transfer_count;
128 const absolute_time_t*
const end) {
130 check_dma_channel_param(channel);
132 assert(!is_nil_time(*end));
134 while(!time_reached(*end)) {
135 if(!dma_channel_is_busy(channel)) {
147 assert(util_uint_in_range(
155 check_irq_param(irq_num);
164 check_dma_channel_param(channel);
165 dma_channel_config cfg = dma_get_channel_config(channel);
166 channel_config_set_irq_quiet(&cfg, quiet);
167 dma_channel_set_config(channel, &cfg,
false);
176 const uint l = base + len - 1;
178 for(uint i = base; i <= l; ++i) {
180 gpio_set_input_enabled(i,
true);
186 check_gpio_param(gpio);
188 gpio_set_dir(gpio,
true);
193 const uint irq_index,
194 const uint pio_interrupt_num,
195 const irq_handler_t handler,
196 const bool enabled) {
198 check_pio_param(pio);
201 assert(handler != NULL);
210 pio_set_irqn_source_enabled(
216 irq_set_exclusive_handler(
227 return util_uint_in_range(
235 const uint irq_index) {
237 check_pio_param(pio);
242 pio_get_index(pio) + irq_index];
244 check_irq_param(irq_num);
254 check_pio_param(pio);
259 pio_get_index(pio) + idx];
261 check_irq_param(irq_num);
269 check_irq_param(irq_num);
286 check_irq_param(irq_num);
302 const uint pio_interrupt_num) {
307 const uint basePis = pis_interrupt0;
308 const uint pis = basePis + pio_interrupt_num;
310 assert(util_uint_in_range(
311 pis, pis_interrupt0, pis_interrupt3));
322 check_pio_param(pio);
325 const uint l = base + len - 1;
327 for(uint i = base; i <= l; ++i) {
329 pio_gpio_init(pio, i);
337 check_pio_param(pio);
339 while(!pio_sm_is_rx_fifo_empty(pio, sm)) {
347 check_pio_param(pio);
349 const uint instr = pio_encode_push(
false,
false);
350 while(!pio_sm_is_rx_fifo_empty(pio, sm)) {
351 pio_sm_exec(pio, sm, instr);
358 check_pio_param(pio);
360 const uint instr = pio_encode_pull(
false,
false);
361 while(!pio_sm_is_tx_fifo_empty(pio, sm)) {
362 pio_sm_exec(pio, sm, instr);
369 check_pio_param(pio);
371 return (pio->ctrl & (1u << (PIO_CTRL_SM_ENABLE_LSB + sm))) != 0;
375 const uint pio_interrupt_num) {
376 return util_uint_in_range(
383 const uint pio_interrupt_num) {
384 return util_uint_in_range(
392 const uint pio_interrupt_num) {
393 check_pio_param(pio);
395 while(!pio_interrupt_get(pio, pio_interrupt_num)) {
396 tight_loop_contents();
402 const uint pio_interrupt_num) {
403 check_pio_param(pio);
405 while(pio_interrupt_get(pio, pio_interrupt_num)) {
406 tight_loop_contents();
412 const uint pio_interrupt_num,
413 const absolute_time_t*
const end) {
415 check_pio_param(pio);
418 assert(!is_nil_time(*end));
420 while(!time_reached(*end)) {
421 if(!pio_interrupt_get(pio, pio_interrupt_num)) {
432 const uint pio_interrupt_num) {
433 check_pio_param(pio);
436 pio_interrupt_clear(pio, pio_interrupt_num);
441 const uint pio_interrupt_num,
442 const absolute_time_t*
const end) {
444 check_pio_param(pio);
447 assert(!is_nil_time(*end));
449 while(!time_reached(*end)) {
450 if(pio_interrupt_get(pio, pio_interrupt_num)) {
461 const uint pio_interrupt_num,
462 const absolute_time_t*
const end) {
464 check_pio_param(pio);
467 assert(!is_nil_time(*end));
487 uint32_t*
const word,
488 const uint threshold) {
490 check_pio_param(pio);
492 assert(word != NULL);
494 if(pio_sm_get_rx_fifo_level(pio, sm) >= threshold) {
495 *word = pio_sm_get(pio, sm);
503 #undef UTIL_DEF_IN_RANGE_FUNC
void util_irq_set_exclusive_pio_interrupt_num_handler(PIO const pio, const uint irq_index, const uint pio_interrupt_num, const irq_handler_t handler, const bool enabled)
Set and enable an exclusive interrupt handler for a given pio_interrupt_num.
void util_gpio_set_output(const uint gpio)
Initialises and sets GPIO pin to output.
bool util_pio_sm_is_enabled(PIO const pio, const uint sm)
Check whether a given state machine is enabled.
void util_pio_sm_clear_osr(PIO const pio, const uint sm)
Clears a given state machine's OSR.
const uint8_t util_pio_to_irq_map[]
Quick lookup for finding an NVIC IRQ number for a PIO and interrupt index number.
bool util_pio_interrupt_wait_timeout(PIO const pio, const uint pio_interrupt_num, const absolute_time_t *const end)
Waits for a given PIO to be set within the timeout period.
bool util_pio_interrupt_wait_clear_timeout(PIO const pio, const uint pio_interrupt_num, const absolute_time_t *const end)
Waits for a given PIO to be set within the timeout period and then clears it.
PIO const util_pio_get_pio_from_irq(const uint irq_num)
Gets the PIO using the NVIC IRQ number.
bool util_pio_irq_index_is_valid(const uint idx)
Check whether PIO IRQ index is valid.
bool util_routable_pio_interrupt_num_is_valid(const uint pio_interrupt_num)
Check whether a PIO interrupt number is a valid routable interrupt number.
int util_pio_get_index_from_irq(const uint irq_num)
Gets the PIO IRQ index using the NVIC IRQ number.
void util_pio_interrupt_wait_cleared(PIO const pio, const uint pio_interrupt_num)
Waits until a given PIO interrupt is cleared.
void util_pio_sm_clear_isr(PIO const pio, const uint sm)
Clears a given state machine's ISR.
void util_pio_sm_clear_rx_fifo(PIO const pio, const uint sm)
Clears a given state machine's RX FIFO.
int util_dma_get_index_from_irq(const uint irq_num)
Gets the DMA IRQ index using the NVIC IRQ number.
void util_pio_gpio_contiguous_init(PIO const pio, const uint base, const uint len)
Inits GPIO pins for PIO from base to base + len.
uint util_pio_get_pis_from_pio_interrupt_num(const uint pio_interrupt_num)
bool util_dma_channel_wait_for_finish_timeout(const uint channel, const absolute_time_t *const end)
Wait until channel has completed transferring up to a timeout.
void util_dma_channel_set_quiet(const uint channel, const bool quiet)
Sets a DMA channel's IRQ quiet mode.
void util_pio_interrupt_wait_clear(PIO const pio, const uint pio_interrupt_num)
Waits for a given PIO interrupt to be set and then clears it.
void util_gpio_set_contiguous_input_pins(const uint base, const uint len)
Sets GPIO pins from base to base + len to input.
uint util_dma_get_irqn(const uint irq_index)
Gets the NVIC IRQ number based on the DMA IRQ index.
uint util_pio_get_irq_from_index(PIO const pio, const uint idx)
Gets the NVIC PIO IRQ number using a PIO pointer and PIO IRQ index.
uint32_t util_dma_get_transfer_count(const uint channel)
Get the transfer count for a given DMA channel. When a DMA transfer is active, this count is the numb...
bool util_pio_interrupt_wait_cleared_timeout(PIO const pio, const uint pio_interrupt_num, const absolute_time_t *const end)
Waits until the given interrupt is cleared, up to a maximum timeout.
void util_pio_interrupt_wait(PIO const pio, const uint pio_interrupt_num)
Waits for a given PIO interrupt to be set.
bool util_pio_sm_try_get(PIO const pio, const uint sm, uint32_t *const word, const uint threshold)
Attempts to get a word from the state machine's RX FIFO if more than threshold words are in the buffe...
void util_dma_set_exclusive_channel_irq_handler(const uint irq_index, const uint channel, const irq_handler_t handler, const bool enabled)
Set and enable an exclusive handler for a DMA channel.
bool util_dma_irq_index_is_valid(const uint idx)
Check whether a DMA IRQ index is valid.
bool util_pio_interrupt_num_is_valid(const uint pio_interrupt_num)
Check whether a PIO interrupt number is valid.
const uint8_t util_dma_to_irq_map[]
Quick lookup for finding an NVIC IRQ number for a DMA interrupt index number.
#define UTIL_DEF_IN_RANGE_FUNC(TYPE)
uint util_dma_get_irq_from_index(const uint idx)
Gets the NVIC DMA IRQ number using the DMA IRQ index.
uint util_pion_get_irqn(PIO const pio, const uint irq_index)
#define UTIL_PIO_INTERRUPT_NUM_MIN
#define UTIL_PIO_IRQ_INDEX_MIN
#define UTIL_ROUTABLE_PIO_INTERRUPT_NUM_MAX
#define UTIL_PIO_IRQ_INDEX_MAX
#define UTIL_DMA_IRQ_INDEX_MIN
#define UTIL_DMA_IRQ_INDEX_MAX
#define UTIL_ROUTABLE_PIO_INTERRUPT_NUM_MIN
#define UTIL_PIO_INTERRUPT_NUM_MAX