#include "pio.h" void pio_init(struct pio_cfg_s *cfg) { uint32_t val; uint8_t sm = cfg->sm; /* step1: config clock division */ val = getreg32(cfg->pio_base + PIO_SM0_CLKDIV_OFFSET + (PIO_SM1_CLKDIV_OFFSET - PIO_SM0_CLKDIV_OFFSET) * sm); val &= ~PIO_CLKDIV_FRAC_MASK; val |= (cfg->clkdiv_frac << PIO_CLKDIV_FRAC_POS); val &= ~PIO_CLKDIV_INT_MASK; val |= (cfg->clkdiv_int << PIO_CLKDIV_INT_POS); putreg32(val, cfg->pio_base + PIO_SM0_CLKDIV_OFFSET + (PIO_SM1_CLKDIV_OFFSET - PIO_SM0_CLKDIV_OFFSET) * sm); /* step2: disable state machine and restart */ val = getreg32(cfg->pio_base + PIO_CTRL_OFFSET); val &= ~(1 << (PIO_SM_ENABLE_POS + sm)); val |= (1 << (PIO_SM_RESTART_POS + sm)); val |= (1 << (PIO_CLKDIV_RESTART_POS + sm)); putreg32(val, cfg->pio_base + PIO_CTRL_OFFSET); /* step 3: config execution settings for state machine */ val = getreg32(cfg->pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm); val &= ~PIO_STATUS_N_MASK; val |= (cfg->mov_status_level << PIO_STATUS_N_POS); if (cfg->mov_status_sel_rx) { val |= PIO_STATUS_SEL; } else { val &= ~PIO_STATUS_SEL; } val &= ~PIO_WRAP_BOTTOM_MASK; val |= (cfg->wrap_bottom << PIO_WRAP_BOTTOM_POS); val &= ~PIO_WRAP_TOP_MASK; val |= (cfg->wrap_top << PIO_WRAP_TOP_POS); if (cfg->out_sticky) { val |= PIO_OUT_STICKY; } else { val &= ~PIO_OUT_STICKY; } if (cfg->inline_outen) { val |= PIO_INLINE_OUT_EN; } else { val &= ~PIO_INLINE_OUT_EN; } val &= ~PIO_OUT_EN_SEL_MASK; val |= (cfg->outen_sel << PIO_OUT_EN_SEL_POS); val &= ~PIO_JMP_PIN_MASK; val |= (cfg->pin_jmp << PIO_JMP_PIN_POS); if (cfg->side_dest_pindir) { val |= PIO_SIDE_PINDIR; } else { val &= ~PIO_SIDE_PINDIR; } if (cfg->side_optional) { val |= PIO_SIDE_EN; } else { val &= ~PIO_SIDE_EN; } putreg32(val, cfg->pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm); /* step 4: config shift registers for state machine */ val = getreg32(cfg->pio_base + PIO_SM0_SHIFTCTRL_OFFSET + (PIO_SM1_SHIFTCTRL_OFFSET - PIO_SM0_SHIFTCTRL_OFFSET) * sm); if (cfg->auto_push) { val |= PIO_AUTOPUSH; } else { val &= ~PIO_AUTOPUSH; } if (cfg->auto_pull) { val |= PIO_AUTOPULL; } else { val &= ~PIO_AUTOPULL; } if (cfg->in_dir_to_right) { val |= PIO_IN_SHIFTDIR; } else { val &= ~PIO_IN_SHIFTDIR; } if (cfg->out_dir_to_right) { val |= PIO_OUT_SHIFTDIR; } else { val &= ~PIO_OUT_SHIFTDIR; } val &= ~PIO_PUSH_THRESH_MASK; val |= (cfg->thresh_bits_push << PIO_PUSH_THRESH_POS); val &= ~PIO_PULL_THRESH_MASK; val |= (cfg->thresh_bits_pull << PIO_PULL_THRESH_POS); if (cfg->fifo_join == PIO_FIFO_JOIN_NONE) { val &= ~(PIO_FJOIN_TX | PIO_FJOIN_RX); } else if (cfg->fifo_join == PIO_FIFO_RX_JOIN_TX) { val |= PIO_FJOIN_TX; val &= ~PIO_FJOIN_RX; } else if (cfg->fifo_join == PIO_FIFO_TX_JOIN_RX) { val &= ~PIO_FJOIN_TX; val |= PIO_FJOIN_RX; } else { return; } putreg32(val, cfg->pio_base + PIO_SM0_SHIFTCTRL_OFFSET + (PIO_SM1_SHIFTCTRL_OFFSET - PIO_SM0_SHIFTCTRL_OFFSET) * sm); /* step 5: config state machine pin */ val = getreg32(cfg->pio_base + PIO_SM0_PINCTRL_OFFSET + (PIO_SM1_PINCTRL_OFFSET - PIO_SM0_PINCTRL_OFFSET) * sm); val &= ~PIO_OUT_BASE_MASK; val |= (cfg->pin_out_base << PIO_OUT_BASE_POS); val &= ~PIO_SET_BASE_MASK; val |= (cfg->pin_set_base << PIO_SET_BASE_POS); val &= ~PIO_SIDESET_BASE_MASK; val |= (cfg->pin_side_base << PIO_SIDESET_BASE_POS); val &= ~PIO_IN_BASE_MASK; val |= (cfg->pin_in_base << PIO_IN_BASE_POS); val &= ~PIO_OUT_COUNT_MASK; val |= (cfg->pin_out_count << PIO_OUT_COUNT_POS); val &= ~PIO_SET_COUNT_MASK; val |= (cfg->pin_set_count << PIO_SET_COUNT_POS); val &= ~PIO_SIDESET_COUNT_MASK; val |= (cfg->pin_side_count << PIO_SIDESET_COUNT_POS); putreg32(val, cfg->pio_base + PIO_SM0_PINCTRL_OFFSET + (PIO_SM1_PINCTRL_OFFSET - PIO_SM0_PINCTRL_OFFSET) * sm); } void pio_enable(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (1 << (PIO_SM_ENABLE_POS + sm)); val |= (1 << (PIO_SM_RESTART_POS + sm)); val |= (1 << (PIO_CLKDIV_RESTART_POS + sm)); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_disable(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val &= ~(1 << (PIO_SM_ENABLE_POS + sm)); val |= (1 << (PIO_SM_RESTART_POS + sm)); val |= (1 << (PIO_CLKDIV_RESTART_POS + sm)); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_enable_multi(uint32_t pio_base, uint8_t sms) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (sms << PIO_SM_ENABLE_POS); val |= (sms << PIO_SM_RESTART_POS); val |= (sms << PIO_CLKDIV_RESTART_POS); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_disable_multi(uint32_t pio_base, uint8_t sms) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val &= ~(sms << PIO_SM_ENABLE_POS); val |= (sms << PIO_SM_RESTART_POS); val |= (sms << PIO_CLKDIV_RESTART_POS); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_restart(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (1 << (PIO_SM_RESTART_POS + sm)); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_restart_multi(uint32_t pio_base, uint8_t sms) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (sms << PIO_SM_RESTART_POS); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_clkdiv_restart(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (1 << (PIO_CLKDIV_RESTART_POS + sm)); putreg32(val, pio_base + PIO_CTRL_OFFSET); } void pio_clkdiv_restart_multi(uint32_t pio_base, uint8_t sms) { uint32_t val; val = getreg32(pio_base + PIO_CTRL_OFFSET); val |= (sms << PIO_CLKDIV_RESTART_POS); putreg32(val, pio_base + PIO_CTRL_OFFSET); } uint32_t pio_fifo_get_status(uint32_t pio_base, uint8_t sm) { return getreg32(pio_base + PIO_FSTAT_OFFSET); } uint8_t pio_fifo_get_tx_level(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_FLEVEL_OFFSET); val >>= ((PIO_FLEVEL_TX1_POS - PIO_FLEVEL_TX0_POS) * sm); val &= PIO_FLEVEL_TX0_MASK; val >>= PIO_FLEVEL_TX0_POS; return (uint8_t)val; } uint8_t pio_fifo_get_rx_level(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_FLEVEL_OFFSET); val >>= ((PIO_FLEVEL_RX1_POS - PIO_FLEVEL_RX0_POS) * sm); val &= PIO_FLEVEL_RX0_MASK; val >>= PIO_FLEVEL_RX0_POS; return (uint8_t)val; } void pio_fifo_write(uint32_t pio_base, uint8_t sm, uint32_t value) { putreg32(value, pio_base + PIO_TXF0_OFFSET + (PIO_TXF1_OFFSET - PIO_TXF0_OFFSET) * sm); } uint32_t pio_fifo_read(uint32_t pio_base, uint8_t sm) { return getreg32(pio_base + PIO_RXF0_OFFSET + (PIO_RXF1_OFFSET - PIO_RXF0_OFFSET) * sm); } void pio_flag_clear(uint32_t pio_base, uint8_t flag) { putreg32(1 << flag, pio_base + PIO_IRQ_OFFSET); } void pio_flag_set(uint32_t pio_base, uint8_t flag) { putreg32(1 << flag, pio_base + PIO_IRQ_FORCE_OFFSET); } void pio_flag_clear_multi(uint32_t pio_base, uint8_t flags) { putreg32(flags, pio_base + PIO_IRQ_OFFSET); } void pio_flag_set_multi(uint32_t pio_base, uint8_t flags) { putreg32(flags, pio_base + PIO_IRQ_FORCE_OFFSET); } uint8_t pio_addr_get(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_SM0_ADDR_OFFSET + (PIO_SM1_ADDR_OFFSET - PIO_SM0_ADDR_OFFSET) * sm); val &= PIO_ADDR_MASK; val >>= PIO_ADDR_POS; return (uint8_t)val; } uint16_t pio_instr_get(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_SM0_INSTR_OFFSET + (PIO_SM1_INSTR_OFFSET - PIO_SM0_INSTR_OFFSET) * sm); val &= PIO_INSTR_MASK; val >>= PIO_INSTR_POS; return (uint16_t)val; } void pio_instr_insert(uint32_t pio_base, uint8_t sm, uint16_t instr) { uint32_t val; val = getreg32(pio_base + PIO_SM0_INSTR_OFFSET + (PIO_SM1_INSTR_OFFSET - PIO_SM0_INSTR_OFFSET) * sm); val &= ~PIO_INSTR_MASK; val |= (instr << PIO_INSTR_POS); putreg32(val, pio_base + PIO_SM0_INSTR_OFFSET); } int pio_instr_is_complete(uint32_t pio_base, uint8_t sm) { uint32_t val; val = getreg32(pio_base + PIO_SM0_EXECCTRL_OFFSET + (PIO_SM1_EXECCTRL_OFFSET - PIO_SM0_EXECCTRL_OFFSET) * sm); val &= PIO_EXEC_STALLED; if (val) { return 0; } else { return 1; } } void pio_instr_place(uint32_t pio_base, uint8_t addr, uint16_t instr) { putreg32(instr, pio_base + PIO_INSTR_MEM0_OFFSET + (PIO_INSTR_MEM1_OFFSET - PIO_INSTR_MEM0_OFFSET) * addr); } uint32_t pio_int_get_raw_status(uint32_t pio_base) { return getreg32(pio_base + PIO_INTR_OFFSET); } uint32_t pio_int_get_status(uint32_t pio_base, uint8_t int_group) { return getreg32(pio_base + PIO_IRQ0_INTS_OFFSET + (PIO_IRQ1_INTS_OFFSET - PIO_IRQ0_INTS_OFFSET) * int_group); } void pio_int_enable(uint32_t pio_base, uint8_t int_group, uint32_t int_type) { uint32_t val; val = getreg32(pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group); val |= int_type; putreg32(val, pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group); } void pio_int_disable(uint32_t pio_base, uint8_t int_group, uint32_t int_type) { uint32_t val; val = getreg32(pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group); val &= ~int_type; putreg32(val, pio_base + PIO_IRQ0_INTE_OFFSET + (PIO_IRQ1_INTE_OFFSET - PIO_IRQ0_INTE_OFFSET) * int_group); } void pio_int_force(uint32_t pio_base, uint8_t int_group, uint32_t int_type) { uint32_t val; val = getreg32(pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group); val |= int_type; putreg32(val, pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group); } void pio_int_deforce(uint32_t pio_base, uint8_t int_group, uint32_t int_type) { uint32_t val; val = getreg32(pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group); val &= ~int_type; putreg32(val, pio_base + PIO_IRQ0_INTF_OFFSET + (PIO_IRQ1_INTF_OFFSET - PIO_IRQ0_INTF_OFFSET) * int_group); }