You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-06-07 04:55:36 +00:00
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>
104 lines
2.6 KiB
Plaintext
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);
|
|
}
|
|
%}
|