.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) } %}