“Last time I moved, I set up my receiver and speakers across the room from my desk and computer. It’s a pretty long (~20 feet) cable run. I was worried the audio quality would degrade over that distance, especially over my cheap cables. While that didn’t end up being a issue, I considered a lot of possible solutions, like using differential signals, Bluetooth, PulseAudio, or S/PDIF. While I have no need for a S/PDIF decoder since the analog signal works just fine, the idea stuck rattled around in my head for a while. My STM32L476 Discovery board has an I2S DAC on it, but no hardware S/PDIF decoder, so I figured it would be fun to write a S/PDIF to I2S converter.
S/PDIF Primer
Note: S/PDIF supports many audio formats. This only talks about 16 bit raw PCM mode.
S/PDIF uses biphase mark encoding to create a self clocking signal. S/PDIF sends its data in frames, each of which is made of two subframes. Each subframe is a sample for a channel. Each subframe starts with a synchronization pattern (which is not biphase mark encoded) which denotes both the start of frame as well as a which channel it is. STM has an application note on using their higher end microcontrollers to decode S/PDIF using a built in hardware peripheral, but it also includes information on the protocol itself, if you want to learn more.
To decode S/PDIF there are a few basic steps:
Recover the clock so you can read the incoming data
Find the start of the frame and synchronize the stream so you can read frames
Read in the data
Decode the biphase mark encoding and extract the data
S/PDIF also sends metadata about the signal, its source, etc, but in my case I didn’t care so I ignored it.”