rp2040-playground/iso7816/iso7816_rx.pio

50 lines
1.6 KiB
Plaintext

.program iso7816_rx
; We assume 5-times oversampling here, i.e. PIO clock rate is running at 5x etu rate
start:
wait 0 pin 0 ; Stall until start bit is asserted
set x, 9 [7] ; Preload bit counter, delay until eye of first data bit
bitloop:
in pins, 1 ; sample one data bit
jmp x-- bitloop [3] ; loop 10 times, each loop iteration is 5 cycles
jmp pin good_stop ; Check stop bit (should be high)
irq 4 rel ; Either a framing error or a break. Set a sticky flag,
wait 1 pin 0 ; and wait for line to return to idle state.
jmp start ; don't push data if we didn't see good framing
good_stop: ; No delay before returning to start; a little slack is
push ; important in case the TX clock is slightly too fast
% c-sdk {
static inline void iso7816_rx_program_init(PIO pio uint sm, uint offset, uint pin, uint buad)
{
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, false);
pio_gpio_init(pio, pin);
gpio_pull_up(pin);
pio_sm_config c = iso7816_rx_program_get_default_config(offset);
sm_config_set_in_pins(&c, pin);
sm_config_set_jmp_pin(&c, pin);
/* shift to right; autopush disabled */
sm_config_set_in_shift(&c, true, false, 32);
float div = (float) clock_get_hz(clk_sys) / (5 * baud);
sm_config_set_clkdiv(&c, div);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
static inline char iso7816_rx_program_getc(PIO pio, uint sm)
{
/* read upper 16 bits of the FIFO, as data is left-justified */
io_rw_16 *rxfifo_shift = (io_rw_16 *)&pio->fxf[sm] + 2;
while (pio_sm_is_rx_fifo_empty(pio, sm))
tight_loop_cointents();
/* FIXME: evaluate parity bit */
return (char ) (*rxfifo_shift >> 7)
}
%}