mspbsldump/nmigen/trigctl.pio

119 lines
2.9 KiB
Plaintext

.program trigctl
; autopull should be on, depth 32
;
; input pin 0: trigger input
;
; set pin 0: glitch output
;
; irq 0 rel: PIO->CM0 "has glitched" signal
; irq 1 rel: CM0->PIO "do a glitch now" signal
public _start:
out x, 32 ; offset
out y, 32 ; length
irq clear 0 rel
public waitinsn:
wait 1 pin 0 ; or "wait irq 1 rel"
offloop:
jmp x-- offloop
set pins, 1
lenloop:
jmp y-- lenloop
set pins, 0
irq set 0 rel
public wait2:
wait 0 pin 0 ; or "nop"
% c-sdk {
enum glitch_polarity {
glitch_positive = 0,
glitch_negative = 1
};
enum trigctl_source {
trig_source_pin,
trig_source_irq
};
static inline void trigctl_pio_init(PIO pio, uint sm, uint prog_offs,
enum trigctl_source trigsrc, uint glitch_pin, uint trig_pin/*,
enum glitch_polarity trig_in_pol, enum glitch_polarity glitch_out_pol*/
, bool enable, int divider) {
pio_sm_set_enabled(pio, sm, false);
if (trigsrc == trig_source_irq) {
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
pio_encode_wait_irq(true, true, 1);
pio->instr_mem[prog_offs + trigctl_offset_wait2] =
pio_encode_nop();
} else {
pio->instr_mem[prog_offs + trigctl_offset_waitinsn] =
pio_encode_wait_pin(true, 0);
pio->instr_mem[prog_offs + trigctl_offset_wait2] =
pio_encode_wait_pin(false, 0);
}
pio_sm_config c = trigctl_program_get_default_config(prog_offs);
sm_config_set_set_pins(&c, glitch_pin, 1);
sm_config_set_in_pins(&c, trig_pin/*, 1*/);
sm_config_set_out_shift(&c, false, true, 32);
sm_config_set_in_shift(&c, false, true, 32);
sm_config_set_clkdiv(&c, divider);
if (trigsrc == trig_source_irq) {
sm_config_set_wrap(&c, prog_offs + trigctl_wrap_target,
prog_offs + trigctl_wrap - 1);
}
pio_sm_init(pio, sm, prog_offs, &c);
pio_sm_set_consecutive_pindirs(pio, sm, glitch_pin, 1, true );
pio_sm_set_consecutive_pindirs(pio, sm, trig_pin , 1, false);
pio_sm_set_pins_with_mask(pio, sm, 0, 1u << glitch_pin);
pio_sm_set_enabled(pio, sm, enable);
pio_gpio_init(pio, glitch_pin);
pio_gpio_init(pio, trig_pin);
}
// ony use "use_wfi" when the corresponding IRQ is enabled in the NVIC
static inline void trigctl_wait_glitch_irq(PIO pio, uint sm, bool use_wfi) {
uint mask = 1u << ((sm + 0) & 3);
if (use_wfi) {
while (!(pio->irq & mask)) __WFE();
} else {
while (!(pio->irq & mask)) ;
}
}
static inline void trigctl_ack_glitch_irq(PIO pio, uint sm) {
hw_set_bits(&pio->irq, 1 << ((sm + 0) & 3));
}
// nvic_irqno: corresponding NVIC IRQ will be PIO${pio}_IRQ_${nvic_irqno}
static inline void trigctl_set_glitch_irq_enabled(PIO pio, uint sm, uint nvic_irqno, bool en) {
pio_set_irqn_source_enabled(pio, nvic_irqno, (sm + 0) & 3, en);
}
/*static inline void trigctl_send_trig_irq(PIO pio, uint sm) {
pio->irq_force = 1 << ((sm + 1) & 3);
}*/
static inline void trigctl_push_off_len(PIO pio, uint sm, uint32_t off, uint32_t len) {
while (pio_sm_is_tx_fifo_full(pio, sm)) ;
pio->txf[sm] = off;
while (pio_sm_is_tx_fifo_full(pio, sm)) ;
pio->txf[sm] = len;
}
%}