; ; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. ; ; SPDX-License-Identifier: BSD-3-Clause ; ; Transmit a mono or stereo I2S audio stream as stereo ; This is 16 bits per sample; can be altered by modifying the "set" params, ; or made programmable by replacing "set x" with "mov x, y" and using Y as a config register. ; ; Autopull must be enabled, with threshold set to 32. ; Since I2S is MSB-first, shift direction should be to left. ; Hence the format of the FIFO word is: ; ; | 31 : 16 | 15 : 0 | ; | sample ws=0 | sample ws=1 | ; ; Data is output at 1 bit per clock. Use clock divider to adjust frequency. ; Fractional divider will probably be needed to get correct bit clock period, ; but for common syslck freqs this should still give a constant word select period. ; ; One output pin is used for the data output. ; Two side-set pins are used. Bit 0 is clock, bit 1 is word select. ; Send 16 bit words to the PIO for mono, 32 bit words for stereo .program audio_i2s .side_set 2 ; /--- LRCLK ; |/-- BCLK bitloop1: ; || out pins, 1 side 0b10 jmp x-- bitloop1 side 0b11 out pins, 1 side 0b00 set x, 14 side 0b01 bitloop0: out pins, 1 side 0b00 jmp x-- bitloop0 side 0b01 out pins, 1 side 0b10 public entry_point: set x, 14 side 0b11 % c-sdk { static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) { pio_sm_config sm_config = audio_i2s_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, 32); 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_with_mask(pio, sm, 0, pin_mask); // clear pins pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point)); } %}