Datasheet

Table Of Contents
43
44 do_nack:
45 jmp y-- entry_point ; Continue if NAK was expected
46 irq wait 0 rel ; Otherwise stop, ask for help
47
48 do_byte:
49 set x, 7 ; Loop 8 times
50 bitloop:
51 out pindirs, 1 [7] ; Serialise write data (all-ones if reading)
52 nop side 1 [2] ; SCL rising edge
53 wait 1 pin, 1 [4] ; Allow clock to be stretched
54 in pins, 1 [7] ; Sample read data in middle of SCL pulse
55 jmp x-- bitloop side 0 [7] ; SCL falling edge
56
57 ; Handle ACK pulse
58 out pindirs, 1 [7] ; On reads, we provide the ACK.
59 nop side 1 [7] ; SCL rising edge
60 wait 1 pin, 1 [7] ; Allow clock to be stretched
61 jmp pin do_nack side 0 [2] ; Test SDA for ACK/NAK, fall through if ACK
62
63 public entry_point:
64 .wrap_target
65 out x, 6 ; Unpack Instr count
66 out y, 1 ; Unpack the NAK ignore bit
67 jmp !x do_byte ; Instr == 0, this is a data record.
68 out null, 32 ; Instr > 0, remainder of this OSR is invalid
69 do_exec:
70 out exec, 16 ; Execute one instruction per FIFO word
71 jmp x-- do_exec ; Repeat n + 1 times
72 .wrap
The IO mapping required by the I2C program is quite complex, due to the different ways that the two serial lines must be
driven and sampled. One interesting feature is that state machine must drive the output enable high when the output is
low, since the bus is open-drain, so the sense of the data is inverted. This could be handled in the PIO program (e.g. mov
osr, ~osr), but instead we can use the IO controls on RP2040 to perform this inversion in the GPIO muxes, saving an
instruction.
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/pio/i2c/i2c.pio Lines 80 - 119
Ê80 static inline void i2c_program_init(PIO pio, uint sm, uint offset, uint pin_sda, uint
Ê pin_scl) {
Ê81 assert(pin_scl == pin_sda + 1);
Ê82 pio_sm_config c = i2c_program_get_default_config(offset);
Ê83
Ê84 // IO mapping
Ê85 sm_config_set_out_pins(&c, pin_sda, 1);
Ê86 sm_config_set_set_pins(&c, pin_sda, 1);
Ê87 sm_config_set_in_pins(&c, pin_sda);
Ê88 sm_config_set_sideset_pins(&c, pin_scl);
Ê89 sm_config_set_jmp_pin(&c, pin_sda);
Ê90
Ê91 sm_config_set_out_shift(&c, false, true, 16);
Ê92 sm_config_set_in_shift(&c, false, true, 8);
Ê93
Ê94 float div = (float)clock_get_hz(clk_sys) / (32 * 100000);
Ê95 sm_config_set_clkdiv(&c, div);
Ê96
Ê97 // Try to avoid glitching the bus while connecting the IOs. Get things set
Ê98 // up so that pin is driven down when PIO asserts OE low, and pulled up
Ê99 // otherwise.
100 gpio_pull_up(pin_scl);
RP2040 Datasheet
3.6. Examples 381