Skip to content

Fix RP2xxx I2SOut reversed channels #10250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 134 additions & 104 deletions ports/raspberrypi/common-hal/audiobusio/I2SOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,122 +19,152 @@
#include "bindings/rp2pio/StateMachine.h"

const uint16_t i2s_program[] = {
// ; Load the next set of samples
// ; /--- LRCLK
// ; |/-- BCLK
// ; ||
// pull noblock side 0b01 ; Loads OSR with the next FIFO value or X
0x8880,
// mov x osr side 0b01 ; Save the new value in case we need it again
0xa827,
// set y 14 side 0b01
0xe84e,
// bitloop1:
// out pins 1 side 0b00 [2]
0x6201,
// jmp y-- bitloop1 side 0b01 [2]
0x0a83,
// out pins 1 side 0b10 [2]
0x7201,
// set y 14 side 0b11 [2]
0xfa4e,
// bitloop0:
// out pins 1 side 0b10 [2]
0x7201,
// jmp y-- bitloop0 side 0b11 [2]
0x1a87,
// out pins 1 side 0b00 [2]
0x6201

/* From i2s.pio:

.program i2s
.side_set 2

; Load the next set of samples
; /--- LRCLK
; |/-- BCLK
; ||
pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
mov x osr side 0b11 ; Save the new value in case we need it again
set y 14 side 0b11
bitloop1:
out pins 1 side 0b10 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b00 [2]
set y 14 side 0b01 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b01 [2]
out pins 1 side 0b10 [2]
*/
// Above assembled with pioasm.
0x9880, // 0: pull noblock side 3
0xb827, // 1: mov x, osr side 3
0xf84e, // 2: set y, 14 side 3
0x7201, // 3: out pins, 1 side 2 [2]
0x1a83, // 4: jmp y--, 3 side 3 [2]
0x6201, // 5: out pins, 1 side 0 [2]
0xea4e, // 6: set y, 14 side 1 [2]
0x6201, // 7: out pins, 1 side 0 [2]
0x0a87, // 8: jmp y--, 7 side 1 [2]
0x7201, // 9: out pins, 1 side 2 [2]
};


const uint16_t i2s_program_left_justified[] = {
// ; Load the next set of samples
// ; /--- LRCLK
// ; |/-- BCLK
// ; ||
// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
0x9880,
// mov x osr side 0b11 ; Save the new value in case we need it again
0xb827,
// set y 14 side 0b11
0xf84e,
// bitloop1:
// out pins 1 side 0b00 [2]
0x6201,
// jmp y-- bitloop1 side 0b01 [2]
0x0a83,
// out pins 1 side 0b00 [2]
0x6201,
// set y 14 side 0b01 [2]
0xea4e,
// bitloop0:
// out pins 1 side 0b10 [2]
0x7201,
// jmp y-- bitloop0 side 0b11 [2]
0x1a87,
// out pins 1 side 0b10 [2]
0x7201
/* From i2s_left.pio:

.program i2s
.side_set 2

; Load the next set of samples
; /--- LRCLK
; |/-- BCLK
; ||
pull noblock side 0b01 ; Loads OSR with the next FIFO value or X
mov x osr side 0b01 ; Save the new value in case we need it again
set y 14 side 0b01
bitloop1:
out pins 1 side 0b10 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b10 [2]
set y 14 side 0b11 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b01 [2]
out pins 1 side 0b00 [2]
*/
// Above assembled with pioasm.
0x8880, // 0: pull noblock side 1
0xa827, // 1: mov x, osr side 1
0xe84e, // 2: set y, 14 side 1
0x7201, // 3: out pins, 1 side 2 [2]
0x1a83, // 4: jmp y--, 3 side 3 [2]
0x7201, // 5: out pins, 1 side 2 [2]
0xfa4e, // 6: set y, 14 side 3 [2]
0x6201, // 7: out pins, 1 side 0 [2]
0x0a87, // 8: jmp y--, 7 side 1 [2]
0x6201, // 9: out pins, 1 side 0 [2]
};

// Another version of i2s_program with the LRCLC and BCLK pin swapped
const uint16_t i2s_program_swap[] = {
// ; Load the next set of samples
// ; /--- BCLK
// ; |/-- LRCLK
// ; ||
// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
0x9880,
// mov x osr side 0b11 ; Save the new value in case we need it again
0xb827,
// set y 14 side 0b11
0xf84e,
// bitloop1:
// out pins 1 side 0b01 [2]
0x6a01,
// jmp y-- bitloop1 side 0b11 [2]
0x1a83,
// out pins 1 side 0b00 [2]
0x6201,
// set y 14 side 0b10 [2]
0xf24e,
// bitloop0:
// out pins 1 side 0b00 [2]
0x6201,
// jmp y-- bitloop0 side 0b10 [2]
0x1287,
// out pins 1 side 0b01 [2]
0x6a01
/* From i2s_swap.pio:

.program i2s
.side_set 2

; Load the next set of samples
; /--- BCLK
; |/-- LRCLK
; ||
pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
mov x osr side 0b11 ; Save the new value in case we need it again
set y 14 side 0b11
bitloop1:
out pins 1 side 0b01 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b00 [2]
set y 14 side 0b10 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b10 [2]
out pins 1 side 0b01 [2]
*/
// Above assembled with pioasm.
0x9880, // 0: pull noblock side 3
0xb827, // 1: mov x, osr side 3
0xf84e, // 2: set y, 14 side 3
0x6a01, // 3: out pins, 1 side 1 [2]
0x1a83, // 4: jmp y--, 3 side 3 [2]
0x6201, // 5: out pins, 1 side 0 [2]
0xf24e, // 6: set y, 14 side 2 [2]
0x6201, // 7: out pins, 1 side 0 [2]
0x1287, // 8: jmp y--, 7 side 2 [2]
0x6a01, // 9: out pins, 1 side 1 [2]
};

// Another version of i2s_program_left_justified with the LRCLC and BCLK pin
// swapped.
const uint16_t i2s_program_left_justified_swap[] = {
// ; Load the next set of samples
// ; /--- BCLK
// ; |/-- LRCLK
// ; ||
// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
0x9880,
// mov x osr side 0b11 ; Save the new value in case we need it again
0xb827,
// set y 14 side 0b11
0xf84e,
// bitloop1:
// out pins 1 side 0b00 [2]
0x6201,
// jmp y-- bitloop1 side 0b10 [2]
0x1283,
// out pins 1 side 0b00 [2]
0x6201,
// set y 14 side 0b10 [2]
0xf24e,
// bitloop0:
// out pins 1 side 0b01 [2]
0x6a01,
// jmp y-- bitloop0 side 0b11 [2]
0x1a87,
// out pins 1 side 0b01 [2]
0x6a01
/* From i2s_swap_left.pio:

.program i2s
.side_set 2

; Load the next set of samples
; /--- BCLK
; |/-- LRCLK
; ||
pull noblock side 0b10 ; Loads OSR with the next FIFO value or X
mov x osr side 0b10 ; Save the new value in case we need it again
set y 14 side 0b10
bitloop1:
out pins 1 side 0b01 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b01 [2]
set y 14 side 0b11 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b10 [2]
out pins 1 side 0b00 [2]
*/
// Above assembled with pioasm.
0x9080, // 0: pull noblock side 2
0xb027, // 1: mov x, osr side 2
0xf04e, // 2: set y, 14 side 2
0x6a01, // 3: out pins, 1 side 1 [2]
0x1a83, // 4: jmp y--, 3 side 3 [2]
0x6a01, // 5: out pins, 1 side 1 [2]
0xfa4e, // 6: set y, 14 side 3 [2]
0x6201, // 7: out pins, 1 side 0 [2]
0x1287, // 8: jmp y--, 7 side 2 [2]
0x6201, // 9: out pins, 1 side 0 [2]
};

void i2sout_reset(void) {
Expand Down
7 changes: 7 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/README.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.pio files right now are compiled by hand with pico-sdk/tools/pioasm and inserted into I2SOut.c

i2s.pio regular pin order, not left_justified
i2s_left.pio regular pin order, left_justified

i2s_swap.pio swapped pin order, not left_justified
i2s_swap_left.pio swapped pin order, left_justified
25 changes: 25 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/i2s.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; This file is part of the CircuitPython project: https://circuitpython.org
;
; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries
;
; SPDX-License-Identifier: MIT

.program i2s
.side_set 2

; Load the next set of samples
; /--- LRCLK
; |/-- BCLK
; ||
pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
mov x osr side 0b11 ; Save the new value in case we need it again
set y 14 side 0b11
bitloop1:
out pins 1 side 0b10 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b00 [2]
set y 14 side 0b01 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b01 [2]
out pins 1 side 0b10 [2]
25 changes: 25 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/i2s_left.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; This file is part of the CircuitPython project: https://circuitpython.org
;
; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries
;
; SPDX-License-Identifier: MIT

.program i2s
.side_set 2

; Load the next set of samples
; /--- LRCLK
; |/-- BCLK
; ||
pull noblock side 0b01 ; Loads OSR with the next FIFO value or X
mov x osr side 0b01 ; Save the new value in case we need it again
set y 14 side 0b01
bitloop1:
out pins 1 side 0b10 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b10 [2]
set y 14 side 0b11 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b01 [2]
out pins 1 side 0b00 [2]
25 changes: 25 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/i2s_swap.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; This file is part of the CircuitPython project: https://circuitpython.org
;
; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries
;
; SPDX-License-Identifier: MIT

.program i2s
.side_set 2

; Load the next set of samples
; /--- BCLK
; |/-- LRCLK
; ||
pull noblock side 0b11 ; Loads OSR with the next FIFO value or X
mov x osr side 0b11 ; Save the new value in case we need it again
set y 14 side 0b11
bitloop1:
out pins 1 side 0b01 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b00 [2]
set y 14 side 0b10 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b10 [2]
out pins 1 side 0b01 [2]
25 changes: 25 additions & 0 deletions ports/raspberrypi/common-hal/audiobusio/i2s_swap_left.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; This file is part of the CircuitPython project: https://circuitpython.org
;
; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries
;
; SPDX-License-Identifier: MIT

.program i2s
.side_set 2

; Load the next set of samples
; /--- BCLK
; |/-- LRCLK
; ||
pull noblock side 0b10 ; Loads OSR with the next FIFO value or X
mov x osr side 0b10 ; Save the new value in case we need it again
set y 14 side 0b10
bitloop1:
out pins 1 side 0b01 [2] ; Right channel first
jmp y-- bitloop1 side 0b11 [2]
out pins 1 side 0b01 [2]
set y 14 side 0b11 [2]
bitloop0:
out pins 1 side 0b00 [2] ; Then left channel
jmp y-- bitloop0 side 0b10 [2]
out pins 1 side 0b00 [2]
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy