0
mirror of https://github.com/torvalds/GuitarPedal.git synced 2026-06-07 04:55:36 +00:00
Files
Linus Torvalds 77f75a30b9 Bring in my rp2350 PIO files
The important one is the i2s decoding and encoding to do the audio
interfacing with the TAC5112.  But I'm also doing button debouncing and
the rotary encoder quadrature decoding in PIO programs.

There's also a PIO program for the WS2812 smart LED that I was using at
one point.  The current board doesn't actually use that, because it
didn't fit the form factor, but I should probably go back to it at some
point when I do a separate board for the stomp switch and associated
LEDs.

So right now I'm just doing plain PWM on flat-top 5mm single-color LEDs,
but I think the WS2812 might make a comeback some day, so the PIO
program for dealing with it remains.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2026-05-13 14:26:37 -07:00

104 lines
2.6 KiB
Plaintext

;
; We want a target sample frequency of 48kHz, which
; with 24-bit i2s data means a dot clock of 2.304MHz.
;
; We overclock the rp2354 slightly to 172.8MHz, which
; is exactly 75x that dot clock frequency.
;
; We then use a PIO divider of 25, and make the PIO
; program do 3 cycles per clock.
;
; This means that all dividers are nice integers and
; there is no clock jitter due to any fractional cycles.
;
; i2s: FSYNC and each data bit is transmitted on the
; falling edge of BCLK, so we set those bits the cycle
; when BCLK goes low ("side 0") so that they are stable
; on the rising edge ("side 1").
;
; The actual data is transmitted one cycle after FSYNC
; goes low
;
.pio_version 1
.program i2s_tx
.fifo tx
.clock_div 25
.side_set 2
.out 1 left
.wrap_target
pull noblock [1] side 0b00 ; cycle 0: FSYNC goes LOW
set x,22 side 0b01
loop_low:
out pins,1 [1] side 0b00 ; cycles 1..23: DOUT wiggles
jmp x-- loop_low side 0b01
out pins,1 [1] side 0b10 ; cycle 24: FSYNC goes HIGH
set x,22 side 0b11
loop_high:
nop [1] side 0b10 ; cycles 25-47
jmp x-- loop_high side 0b11
.wrap
% c-sdk {
//
// 'pin' is BCLK (MCU output)
// 'pin+1' is FSYNC (MCU output)
// 'pin+2' is DIN (MCU output! It's DIN from the CODEC standpoint!)
// 'pin+3' is DOUT (MCU input! It's DOUT from the CODEC standpoint!)
//
static inline void i2s_tx_program_init(PIO pio, uint sm, uint offset, uint pin)
{
pio_sm_config c = i2s_tx_program_get_default_config(offset);
pio_gpio_init(pio, pin);
pio_gpio_init(pio, pin+1);
pio_gpio_init(pio, pin+2);
pio_gpio_init(pio, pin+3);
// three output pins, one input
pio_sm_set_pindirs_with_mask(pio, sm, 0b0111 << pin, 0b1111 << pin);
// BCLK and FSYNC using sideset
sm_config_set_sideset_pin_base(&c, pin);
// DOUT using 'OUT' instruction
sm_config_set_out_pins(&c, pin+2, 1);
// Load and run the program
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}
.program i2s_rx
.fifo rx
.clock_div 25
.in 1 left
.wrap_target
set x,23
wait 0 jmppin [3] ; wait for FSYNC going low
; then delay to sample in the middle of valid window
loop_in:
in pins,1 [1] ; read DIN and delay to make loop exactly 3 cycles
jmp x-- loop_in
push noblock [14] ; write result and delay before looping
.wrap
% c-sdk {
static inline void i2s_rx_program_init(PIO pio, uint sm, uint offset, uint pin)
{
pio_sm_config c = i2s_rx_program_get_default_config(offset);
sm_config_set_jmp_pin(&c, pin+1); // FSYNC
sm_config_set_in_pins(&c, pin+3); // DOUT
// Load and run the program
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}