Skip to content

Commit c0a26fe

Browse files
Rewrite I2S bidirectional support (#3117)
I2S bidirectional was shifting data out on the wrong clock edge, which would cause failures for setup/hold in some receivers. Rewrite the sampling to separate writing and reading edges. Fixes #3116
1 parent dd1498b commit c0a26fe

File tree

2 files changed

+58
-55
lines changed

2 files changed

+58
-55
lines changed

libraries/I2S/src/pio_i2s.pio

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -238,23 +238,23 @@ right1:
238238

239239
; +----- WCLK
240240
; |+---- BCLK
241-
mov x, y side 0b00 [1]
241+
in pins, 1 side 0b01 ; Adjust for input shift
242+
.wrap_target
243+
mov x, y side 0b01
242244
left1:
243-
out pins, 1 side 0b01
245+
out pins, 1 side 0b00 [1]
244246
in pins, 1 side 0b01
245-
jmp x--, left1 side 0b00 [1]
246-
out pins, 1 side 0b01
247-
in pins, 1 side 0b01 ; 2584 LRCK stays low until BCLK goes low
248-
; Last bit of left has WCLK change per I2S spec
249-
mov x, y side 0b10 [1]
247+
jmp x--, left1 side 0b01
248+
out pins, 1 side 0b10 [1] ; Last bit of left has WCLK change per I2S spec
249+
in pins, 1 side 0b11
250+
mov x, y side 0b11
250251
right1:
251-
out pins, 1 side 0b11
252+
out pins, 1 side 0b10 [1]
252253
in pins, 1 side 0b11
253-
jmp x--, right1 side 0b10 [1]
254-
out pins, 1 side 0b11
255-
in pins, 1 side 0b11 ; 2584 LRCK stays high until BCLK goes low
256-
; Loop back to beginning...
257-
254+
jmp x--, right1 side 0b11
255+
out pins, 1 side 0b00 [1]; Last bit of right also has WCLK change
256+
in pins, 1 side 0b01
257+
.wrap ; Loop back to beginning...
258258

259259
.program pio_i2s_inout_swap ; Note this is the same as _out, just "in" and not "out"
260260
.side_set 2 ; 0 = wclk, 1=bclk
@@ -264,22 +264,23 @@ right1:
264264

265265
; +----- BCLK
266266
; |+---- WCLK
267-
mov x, y side 0b00 [1]
267+
in pins, 1 side 0b10 ; Adjust for input shift
268+
.wrap_target
269+
mov x, y side 0b10
268270
left1:
269-
out pins, 1 side 0b10
271+
out pins, 1 side 0b00 [1]
270272
in pins, 1 side 0b10
271-
jmp x--, left1 side 0b00 [1]
272-
out pins, 1 side 0b10
273-
in pins, 1 side 0b10 ;2584 LRCK stays low until BCLK goes low
274-
275-
mov x, y side 0b01 [1]
273+
jmp x--, left1 side 0b10
274+
out pins, 1 side 0b01 [1] ; Last bit of left has WCLK change per I2S spec
275+
in pins, 1 side 0b11
276+
mov x, y side 0b11
276277
right1:
277-
out pins, 1 side 0b11
278+
out pins, 1 side 0b01 [1]
278279
in pins, 1 side 0b11
279-
jmp x--, right1 side 0b01 [1]
280-
out pins, 1 side 0b11
281-
in pins, 1 side 0b11 ; 2584 LRCK stays high until BCLK goes low
282-
; Loop back to beginning...
280+
jmp x--, right1 side 0b11
281+
out pins, 1 side 0b00 [1]; Last bit of right also has WCLK change
282+
in pins, 1 side 0b10
283+
.wrap ; Loop back to beginning...
283284

284285

285286

libraries/I2S/src/pio_i2s.pio.h

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -433,31 +433,32 @@ static inline pio_sm_config pio_i2s_in_swap_program_get_default_config(uint offs
433433
// pio_i2s_inout //
434434
// ------------- //
435435

436-
#define pio_i2s_inout_wrap_target 0
437-
#define pio_i2s_inout_wrap 11
436+
#define pio_i2s_inout_wrap_target 1
437+
#define pio_i2s_inout_wrap 12
438438
#define pio_i2s_inout_pio_version 0
439439

440440
static const uint16_t pio_i2s_inout_program_instructions[] = {
441+
0x4801, // 0: in pins, 1 side 1
441442
// .wrap_target
442-
0xa122, // 0: mov x, y side 0 [1]
443-
0x6801, // 1: out pins, 1 side 1
444-
0x4801, // 2: in pins, 1 side 1
445-
0x0141, // 3: jmp x--, 1 side 0 [1]
446-
0x6801, // 4: out pins, 1 side 1
447-
0x4801, // 5: in pins, 1 side 1
448-
0xb122, // 6: mov x, y side 2 [1]
449-
0x7801, // 7: out pins, 1 side 3
450-
0x5801, // 8: in pins, 1 side 3
451-
0x1147, // 9: jmp x--, 7 side 2 [1]
452-
0x7801, // 10: out pins, 1 side 3
453-
0x5801, // 11: in pins, 1 side 3
443+
0xa822, // 1: mov x, y side 1
444+
0x6101, // 2: out pins, 1 side 0 [1]
445+
0x4801, // 3: in pins, 1 side 1
446+
0x0842, // 4: jmp x--, 2 side 1
447+
0x7101, // 5: out pins, 1 side 2 [1]
448+
0x5801, // 6: in pins, 1 side 3
449+
0xb822, // 7: mov x, y side 3
450+
0x7101, // 8: out pins, 1 side 2 [1]
451+
0x5801, // 9: in pins, 1 side 3
452+
0x1848, // 10: jmp x--, 8 side 3
453+
0x6101, // 11: out pins, 1 side 0 [1]
454+
0x4801, // 12: in pins, 1 side 1
454455
// .wrap
455456
};
456457

457458
#if !PICO_NO_HARDWARE
458459
static const struct pio_program pio_i2s_inout_program = {
459460
.instructions = pio_i2s_inout_program_instructions,
460-
.length = 12,
461+
.length = 13,
461462
.origin = -1,
462463
.pio_version = pio_i2s_inout_pio_version,
463464
#if PICO_PIO_VERSION > 0
@@ -477,31 +478,32 @@ static inline pio_sm_config pio_i2s_inout_program_get_default_config(uint offset
477478
// pio_i2s_inout_swap //
478479
// ------------------ //
479480

480-
#define pio_i2s_inout_swap_wrap_target 0
481-
#define pio_i2s_inout_swap_wrap 11
481+
#define pio_i2s_inout_swap_wrap_target 1
482+
#define pio_i2s_inout_swap_wrap 12
482483
#define pio_i2s_inout_swap_pio_version 0
483484

484485
static const uint16_t pio_i2s_inout_swap_program_instructions[] = {
486+
0x5001, // 0: in pins, 1 side 2
485487
// .wrap_target
486-
0xa122, // 0: mov x, y side 0 [1]
487-
0x7001, // 1: out pins, 1 side 2
488-
0x5001, // 2: in pins, 1 side 2
489-
0x0141, // 3: jmp x--, 1 side 0 [1]
490-
0x7001, // 4: out pins, 1 side 2
491-
0x5001, // 5: in pins, 1 side 2
492-
0xa922, // 6: mov x, y side 1 [1]
493-
0x7801, // 7: out pins, 1 side 3
494-
0x5801, // 8: in pins, 1 side 3
495-
0x0947, // 9: jmp x--, 7 side 1 [1]
496-
0x7801, // 10: out pins, 1 side 3
497-
0x5801, // 11: in pins, 1 side 3
488+
0xb022, // 1: mov x, y side 2
489+
0x6101, // 2: out pins, 1 side 0 [1]
490+
0x5001, // 3: in pins, 1 side 2
491+
0x1042, // 4: jmp x--, 2 side 2
492+
0x6901, // 5: out pins, 1 side 1 [1]
493+
0x5801, // 6: in pins, 1 side 3
494+
0xb822, // 7: mov x, y side 3
495+
0x6901, // 8: out pins, 1 side 1 [1]
496+
0x5801, // 9: in pins, 1 side 3
497+
0x1848, // 10: jmp x--, 8 side 3
498+
0x6101, // 11: out pins, 1 side 0 [1]
499+
0x5001, // 12: in pins, 1 side 2
498500
// .wrap
499501
};
500502

501503
#if !PICO_NO_HARDWARE
502504
static const struct pio_program pio_i2s_inout_swap_program = {
503505
.instructions = pio_i2s_inout_swap_program_instructions,
504-
.length = 12,
506+
.length = 13,
505507
.origin = -1,
506508
.pio_version = pio_i2s_inout_swap_pio_version,
507509
#if PICO_PIO_VERSION > 0

0 commit comments

Comments
 (0)