; pio_i2s for the Raspberry Pi Pico RP2040 ; ; Based loosely off of the MicroPython I2S code in ; https://github.com/micropython/micropython/blob/master/ports/rp2/machine_i2s.c ; ; Copyright (c) 2022 Earle F. Philhower, III ; ; This library is free software; you can redistribute it and/or ; modify it under the terms of the GNU Lesser General Public ; License as published by the Free Software Foundation; either ; version 2.1 of the License, or (at your option) any later version. ; ; This library is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; Lesser General Public License for more details. ; ; You should have received a copy of the GNU Lesser General Public ; License along with this library; if not, write to the Free Software ; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA .program pio_i2s_out .side_set 2 ; 0 = bclk, 1=wclk ; The C code should place (number of bits/sample - 2) in Y and ; also update the SHIFTCTRL to be 24 or 32 as appropriate ; +----- WCLK ; |+---- BCLK mov x, y side 0b01 left: out pins, 1 side 0b00 jmp x--, left side 0b01 out pins, 1 side 0b10 ; Last bit of left has WCLK change per I2S spec mov x, y side 0b11 right: out pins, 1 side 0b10 jmp x--, right side 0b11 out pins, 1 side 0b00 ; Last bit of right also has WCLK change ; Loop back to beginning... % c-sdk { static inline void pio_i2s_out_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base, uint bits) { pio_gpio_init(pio, data_pin); pio_gpio_init(pio, clock_pin_base); pio_gpio_init(pio, clock_pin_base + 1); pio_sm_config sm_config = pio_i2s_out_program_get_default_config(offset); sm_config_set_out_pins(&sm_config, data_pin, 1); sm_config_set_sideset_pins(&sm_config, clock_pin_base); sm_config_set_out_shift(&sm_config, false, true, (bits <= 16) ? 2 * bits : bits); sm_config_set_fifo_join(&sm_config, PIO_FIFO_JOIN_TX); pio_sm_init(pio, sm, offset, &sm_config); uint pin_mask = (1u << data_pin) | (3u << clock_pin_base); pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask); pio_sm_set_pins(pio, sm, 0); // clear pins pio_sm_exec(pio, sm, pio_encode_set(pio_y, bits - 2)); } %}