Been searching for ways to output HDMI audio from bare metal code and found a thread [1] with some ideas. Since that thread is rather old and I have questions that I cannot ask there I decided to start a new one. At the moment the code at the end of this post only runs on Linux piped to aplay, but the general idea is to implement a solution on a bare metal project that I've been working on for quite some time, hence my post here.
I have a square wave synthesizer which is supposed to generate IEC958 frames and send two signals at different pitches with each signal being sent through one of 2 channels, but the problem is that both signals come out through both channels seemingly at half the pitch, which likely means that the hardware is interpreting the frames as single channel. I believe this is because my subframes have the 4 bits of the synchronization preamble set to 0, but am having trouble understanding how to fit the 8 bit preambles described at Wikipedia [2] in a 4 bit field.
Searching around I found this StackOverflow question [3] in which the accepted answer mentions that the specified preambles are Manchester Coded, but since as I understand it there's no way for more than two consecutive states being both low or high in Manchester Code, and since Wikipedia also states that the specified preamble bits are not Biphase Mark Coded either, I have no idea how to write the synchronization preamble.
The synthesizer code follows:
And the following is how I run it on Linux to output audio from HDMI0 on a Raspberry Pi 4:
Can someone shed some light into this? I might have more questions once I actually start implementing this on bare metal, but for now I would like to get this right.
Thanks in advance!
[1]: viewtopic.php?t=306441&sid=f82fe068919a ... b3f56f4c2a
[2]: https://en.wikipedia.org/wiki/AES3#Sync ... n_preamble
[3]: https://electronics.stackexchange.com/q ... f-preamble
I have a square wave synthesizer which is supposed to generate IEC958 frames and send two signals at different pitches with each signal being sent through one of 2 channels, but the problem is that both signals come out through both channels seemingly at half the pitch, which likely means that the hardware is interpreting the frames as single channel. I believe this is because my subframes have the 4 bits of the synchronization preamble set to 0, but am having trouble understanding how to fit the 8 bit preambles described at Wikipedia [2] in a 4 bit field.
Searching around I found this StackOverflow question [3] in which the accepted answer mentions that the specified preambles are Manchester Coded, but since as I understand it there's no way for more than two consecutive states being both low or high in Manchester Code, and since Wikipedia also states that the specified preamble bits are not Biphase Mark Coded either, I have no idea how to write the synchronization preamble.
The synthesizer code follows:
Code:
#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <unistd.h>// Channel status values taken from https://github.com/raspberrypi/linux/blob/rpi-6.6.y/include/sound/asoundef.huint8_t cs[24] = { 0x4, // Consumer, PCM audio, no copyright, no emphasis. 0x50, // Software original source. 0x0, // Channel (filled in later). 0x22, // 48khz, 50ppm clock. 0xd2, // 16 bit word length, 48khz original sample rate. 0x0, // Copying always allowed.};int compute_parity(uint32_t val);int main(void) { for (uint64_t count = 0; 1; ++ count) { int frame =count % 192; uint32_t val0 = ((count / 120) & 0x1) ? 0x3fff << 12 : 0xc000 << 12; uint32_t val1 = ((count / 80) & 0x1) ? 0x3fff << 12 : 0xc000 << 12; size_t byte =frame >> 3; size_t bit = count & 0x7; uint32_t csbit = (cs[byte] >> bit) & 0x1; val0 |= csbit << 30; val1 |= csbit << 30; // Fill in the channel information for channel 1. if (frame == 20) val1 |= 0x1 << 30; val0 |= compute_parity(val0) << 31; val1 |= compute_parity(val1) << 31; write(STDOUT_FILENO, &val0, sizeof val0); write(STDOUT_FILENO, &val1, sizeof val1); } return EXIT_SUCCESS;}int compute_parity(uint32_t val) { int parity = 0; for (int i = 4; i < 31; ++ i) parity += (val >> i) & 0x1; return parity & 0x1;}
Code:
./wa | aplay -r 48000 -c 2 -f iec958_subframe_le -D hw:CARD=vc4hdmi0
Thanks in advance!
[1]: viewtopic.php?t=306441&sid=f82fe068919a ... b3f56f4c2a
[2]: https://en.wikipedia.org/wiki/AES3#Sync ... n_preamble
[3]: https://electronics.stackexchange.com/q ... f-preamble
Statistics: Posted by Fridux — Thu Apr 18, 2024 10:18 pm